54e3c0474aa28b940c050992abb9e4da1f697256
[szyfrow.git] / docs / szyfrow / hill.html
1 <!doctype html>
2 <html lang="en">
3 <head>
4 <meta charset="utf-8">
5 <meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1" />
6 <meta name="generator" content="pdoc 0.9.1" />
7 <title>szyfrow.hill API documentation</title>
8 <meta name="description" content="" />
9 <link rel="preload stylesheet" as="style" href="https://cdnjs.cloudflare.com/ajax/libs/10up-sanitize.css/11.0.1/sanitize.min.css" integrity="sha256-PK9q560IAAa6WVRRh76LtCaI8pjTJ2z11v0miyNNjrs=" crossorigin>
10 <link rel="preload stylesheet" as="style" href="https://cdnjs.cloudflare.com/ajax/libs/10up-sanitize.css/11.0.1/typography.min.css" integrity="sha256-7l/o7C8jubJiy74VsKTidCy1yBkRtiUGbVkYBylBqUg=" crossorigin>
11 <link rel="stylesheet preload" as="style" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/10.1.1/styles/github.min.css" crossorigin>
12 <style>:root{--highlight-color:#fe9}.flex{display:flex !important}body{line-height:1.5em}#content{padding:20px}#sidebar{padding:30px;overflow:hidden}#sidebar > *:last-child{margin-bottom:2cm}.http-server-breadcrumbs{font-size:130%;margin:0 0 15px 0}#footer{font-size:.75em;padding:5px 30px;border-top:1px solid #ddd;text-align:right}#footer p{margin:0 0 0 1em;display:inline-block}#footer p:last-child{margin-right:30px}h1,h2,h3,h4,h5{font-weight:300}h1{font-size:2.5em;line-height:1.1em}h2{font-size:1.75em;margin:1em 0 .50em 0}h3{font-size:1.4em;margin:25px 0 10px 0}h4{margin:0;font-size:105%}h1:target,h2:target,h3:target,h4:target,h5:target,h6:target{background:var(--highlight-color);padding:.2em 0}a{color:#058;text-decoration:none;transition:color .3s ease-in-out}a:hover{color:#e82}.title code{font-weight:bold}h2[id^="header-"]{margin-top:2em}.ident{color:#900}pre code{background:#f8f8f8;font-size:.8em;line-height:1.4em}code{background:#f2f2f1;padding:1px 4px;overflow-wrap:break-word}h1 code{background:transparent}pre{background:#f8f8f8;border:0;border-top:1px solid #ccc;border-bottom:1px solid #ccc;margin:1em 0;padding:1ex}#http-server-module-list{display:flex;flex-flow:column}#http-server-module-list div{display:flex}#http-server-module-list dt{min-width:10%}#http-server-module-list p{margin-top:0}.toc ul,#index{list-style-type:none;margin:0;padding:0}#index code{background:transparent}#index h3{border-bottom:1px solid #ddd}#index ul{padding:0}#index h4{margin-top:.6em;font-weight:bold}@media (min-width:200ex){#index .two-column{column-count:2}}@media (min-width:300ex){#index .two-column{column-count:3}}dl{margin-bottom:2em}dl dl:last-child{margin-bottom:4em}dd{margin:0 0 1em 3em}#header-classes + dl > dd{margin-bottom:3em}dd dd{margin-left:2em}dd p{margin:10px 0}.name{background:#eee;font-weight:bold;font-size:.85em;padding:5px 10px;display:inline-block;min-width:40%}.name:hover{background:#e0e0e0}dt:target .name{background:var(--highlight-color)}.name > span:first-child{white-space:nowrap}.name.class > span:nth-child(2){margin-left:.4em}.inherited{color:#999;border-left:5px solid #eee;padding-left:1em}.inheritance em{font-style:normal;font-weight:bold}.desc h2{font-weight:400;font-size:1.25em}.desc h3{font-size:1em}.desc dt code{background:inherit}.source summary,.git-link-div{color:#666;text-align:right;font-weight:400;font-size:.8em;text-transform:uppercase}.source summary > *{white-space:nowrap;cursor:pointer}.git-link{color:inherit;margin-left:1em}.source pre{max-height:500px;overflow:auto;margin:0}.source pre code{font-size:12px;overflow:visible}.hlist{list-style:none}.hlist li{display:inline}.hlist li:after{content:',\2002'}.hlist li:last-child:after{content:none}.hlist .hlist{display:inline;padding-left:1em}img{max-width:100%}td{padding:0 .5em}.admonition{padding:.1em .5em;margin-bottom:1em}.admonition-title{font-weight:bold}.admonition.note,.admonition.info,.admonition.important{background:#aef}.admonition.todo,.admonition.versionadded,.admonition.tip,.admonition.hint{background:#dfd}.admonition.warning,.admonition.versionchanged,.admonition.deprecated{background:#fd4}.admonition.error,.admonition.danger,.admonition.caution{background:lightpink}</style>
13 <style media="screen and (min-width: 700px)">@media screen and (min-width:700px){#sidebar{width:30%;height:100vh;overflow:auto;position:sticky;top:0}#content{width:70%;max-width:100ch;padding:3em 4em;border-left:1px solid #ddd}pre code{font-size:1em}.item .name{font-size:1em}main{display:flex;flex-direction:row-reverse;justify-content:flex-end}.toc ul ul,#index ul{padding-left:1.5em}.toc > ul > li{margin-top:.5em}}</style>
14 <style media="print">@media print{#sidebar h1{page-break-before:always}.source{display:none}}@media print{*{background:transparent !important;color:#000 !important;box-shadow:none !important;text-shadow:none !important}a[href]:after{content:" (" attr(href) ")";font-size:90%}a[href][title]:after{content:none}abbr[title]:after{content:" (" attr(title) ")"}.ir a:after,a[href^="javascript:"]:after,a[href^="#"]:after{content:""}pre,blockquote{border:1px solid #999;page-break-inside:avoid}thead{display:table-header-group}tr,img{page-break-inside:avoid}img{max-width:100% !important}@page{margin:0.5cm}p,h2,h3{orphans:3;widows:3}h1,h2,h3,h4,h5,h6{page-break-after:avoid}}</style>
15 <script defer src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/10.1.1/highlight.min.js" integrity="sha256-Uv3H6lx7dJmRfRvH8TH6kJD1TSK1aFcwgx+mdg3epi8=" crossorigin></script>
16 <script>window.addEventListener('DOMContentLoaded', () => hljs.initHighlighting())</script>
17 </head>
18 <body>
19 <main>
20 <article id="content">
21 <header>
22 <h1 class="title">Module <code>szyfrow.hill</code></h1>
23 </header>
24 <section id="section-intro">
25 <details class="source">
26 <summary>
27 <span>Expand source code</span>
28 </summary>
29 <pre><code class="python">import multiprocessing
30 import numpy as np
31 from numpy import matrix
32 from numpy import linalg
33 from szyfrow.support.utilities import *
34 from szyfrow.support.language_models import *
35 from szyfrow.affine import modular_division_table
36
37
38 def hill_encipher(matrix, message_letters, fillvalue=&#39;a&#39;):
39 &#34;&#34;&#34;Hill cipher
40
41 &gt;&gt;&gt; hill_encipher(np.matrix([[7,8], [11,11]]), &#39;hellothere&#39;)
42 &#39;drjiqzdrvx&#39;
43 &gt;&gt;&gt; hill_encipher(np.matrix([[6, 24, 1], [13, 16, 10], [20, 17, 15]]), \
44 &#39;hello there&#39;)
45 &#39;tfjflpznvyac&#39;
46 &#34;&#34;&#34;
47 n = len(matrix)
48 sanitised_message = sanitise(message_letters)
49 if len(sanitised_message) % n != 0:
50 padding = fillvalue[0] * (n - len(sanitised_message) % n)
51 else:
52 padding = &#39;&#39;
53 message = [pos(c) for c in sanitised_message + padding]
54 message_chunks = [message[i:i+n] for i in range(0, len(message), n)]
55 # message_chunks = chunks(message, len(matrix), fillvalue=None)
56 enciphered_chunks = [((matrix * np.matrix(c).T).T).tolist()[0]
57 for c in message_chunks]
58 return cat([unpos(round(l))
59 for l in sum(enciphered_chunks, [])])
60
61 def hill_decipher(matrix, message, fillvalue=&#39;a&#39;):
62 &#34;&#34;&#34;Hill cipher
63
64 &gt;&gt;&gt; hill_decipher(np.matrix([[7,8], [11,11]]), &#39;drjiqzdrvx&#39;)
65 &#39;hellothere&#39;
66 &gt;&gt;&gt; hill_decipher(np.matrix([[6, 24, 1], [13, 16, 10], [20, 17, 15]]), \
67 &#39;tfjflpznvyac&#39;)
68 &#39;hellothereaa&#39;
69 &#34;&#34;&#34;
70 adjoint = linalg.det(matrix)*linalg.inv(matrix)
71 inverse_determinant = modular_division_table[int(round(linalg.det(matrix))) % 26, 1]
72 inverse_matrix = (inverse_determinant * adjoint) % 26
73 return hill_encipher(inverse_matrix, message, fillvalue)
74
75 def hill_break(message, matrix_size=2, fitness=Pletters,
76 number_of_solutions=1, chunksize=500):
77
78 all_matrices = [np.matrix(list(m))
79 for m in itertools.product([list(r)
80 for r in itertools.product(range(26), repeat=matrix_size)],
81 repeat=matrix_size)]
82 valid_matrices = [m for m, d in
83 zip(all_matrices, (int(round(linalg.det(m))) for m in all_matrices))
84 if d != 0
85 if d % 2 != 0
86 if d % 13 != 0 ]
87 with multiprocessing.Pool() as pool:
88 helper_args = [(message, matrix, fitness)
89 for matrix in valid_matrices]
90 # Gotcha: the helper function here needs to be defined at the top level
91 # (limitation of Pool.starmap)
92 breaks = pool.starmap(hill_break_worker, helper_args, chunksize)
93 if number_of_solutions == 1:
94 return max(breaks, key=lambda k: k[1])
95 else:
96 return sorted(breaks, key=lambda k: k[1], reverse=True)[:number_of_solutions]
97
98 def hill_break_worker(message, matrix, fitness):
99 plaintext = hill_decipher(matrix, message)
100 fit = fitness(plaintext)
101 return matrix, fit
102
103 if __name__ == &#34;__main__&#34;:
104 import doctest</code></pre>
105 </details>
106 </section>
107 <section>
108 </section>
109 <section>
110 </section>
111 <section>
112 <h2 class="section-title" id="header-functions">Functions</h2>
113 <dl>
114 <dt id="szyfrow.hill.cat"><code class="name flex">
115 <span>def <span class="ident">cat</span></span>(<span>iterable, /)</span>
116 </code></dt>
117 <dd>
118 <div class="desc"><p>Concatenate any number of strings.</p>
119 <p>The string whose method is called is inserted in between each given string.
120 The result is returned as a new string.</p>
121 <p>Example: '.'.join(['ab', 'pq', 'rs']) -&gt; 'ab.pq.rs'</p></div>
122 </dd>
123 <dt id="szyfrow.hill.hill_break"><code class="name flex">
124 <span>def <span class="ident">hill_break</span></span>(<span>message, matrix_size=2, fitness=&lt;function Pletters&gt;, number_of_solutions=1, chunksize=500)</span>
125 </code></dt>
126 <dd>
127 <div class="desc"></div>
128 <details class="source">
129 <summary>
130 <span>Expand source code</span>
131 </summary>
132 <pre><code class="python">def hill_break(message, matrix_size=2, fitness=Pletters,
133 number_of_solutions=1, chunksize=500):
134
135 all_matrices = [np.matrix(list(m))
136 for m in itertools.product([list(r)
137 for r in itertools.product(range(26), repeat=matrix_size)],
138 repeat=matrix_size)]
139 valid_matrices = [m for m, d in
140 zip(all_matrices, (int(round(linalg.det(m))) for m in all_matrices))
141 if d != 0
142 if d % 2 != 0
143 if d % 13 != 0 ]
144 with multiprocessing.Pool() as pool:
145 helper_args = [(message, matrix, fitness)
146 for matrix in valid_matrices]
147 # Gotcha: the helper function here needs to be defined at the top level
148 # (limitation of Pool.starmap)
149 breaks = pool.starmap(hill_break_worker, helper_args, chunksize)
150 if number_of_solutions == 1:
151 return max(breaks, key=lambda k: k[1])
152 else:
153 return sorted(breaks, key=lambda k: k[1], reverse=True)[:number_of_solutions]</code></pre>
154 </details>
155 </dd>
156 <dt id="szyfrow.hill.hill_break_worker"><code class="name flex">
157 <span>def <span class="ident">hill_break_worker</span></span>(<span>message, matrix, fitness)</span>
158 </code></dt>
159 <dd>
160 <div class="desc"></div>
161 <details class="source">
162 <summary>
163 <span>Expand source code</span>
164 </summary>
165 <pre><code class="python">def hill_break_worker(message, matrix, fitness):
166 plaintext = hill_decipher(matrix, message)
167 fit = fitness(plaintext)
168 return matrix, fit</code></pre>
169 </details>
170 </dd>
171 <dt id="szyfrow.hill.hill_decipher"><code class="name flex">
172 <span>def <span class="ident">hill_decipher</span></span>(<span>matrix, message, fillvalue='a')</span>
173 </code></dt>
174 <dd>
175 <div class="desc"><p>Hill cipher</p>
176 <pre><code class="language-python-repl">&gt;&gt;&gt; hill_decipher(np.matrix([[7,8], [11,11]]), 'drjiqzdrvx')
177 'hellothere'
178 &gt;&gt;&gt; hill_decipher(np.matrix([[6, 24, 1], [13, 16, 10], [20, 17, 15]]), 'tfjflpznvyac')
179 'hellothereaa'
180 </code></pre></div>
181 <details class="source">
182 <summary>
183 <span>Expand source code</span>
184 </summary>
185 <pre><code class="python">def hill_decipher(matrix, message, fillvalue=&#39;a&#39;):
186 &#34;&#34;&#34;Hill cipher
187
188 &gt;&gt;&gt; hill_decipher(np.matrix([[7,8], [11,11]]), &#39;drjiqzdrvx&#39;)
189 &#39;hellothere&#39;
190 &gt;&gt;&gt; hill_decipher(np.matrix([[6, 24, 1], [13, 16, 10], [20, 17, 15]]), \
191 &#39;tfjflpznvyac&#39;)
192 &#39;hellothereaa&#39;
193 &#34;&#34;&#34;
194 adjoint = linalg.det(matrix)*linalg.inv(matrix)
195 inverse_determinant = modular_division_table[int(round(linalg.det(matrix))) % 26, 1]
196 inverse_matrix = (inverse_determinant * adjoint) % 26
197 return hill_encipher(inverse_matrix, message, fillvalue) </code></pre>
198 </details>
199 </dd>
200 <dt id="szyfrow.hill.hill_encipher"><code class="name flex">
201 <span>def <span class="ident">hill_encipher</span></span>(<span>matrix, message_letters, fillvalue='a')</span>
202 </code></dt>
203 <dd>
204 <div class="desc"><p>Hill cipher</p>
205 <pre><code class="language-python-repl">&gt;&gt;&gt; hill_encipher(np.matrix([[7,8], [11,11]]), 'hellothere')
206 'drjiqzdrvx'
207 &gt;&gt;&gt; hill_encipher(np.matrix([[6, 24, 1], [13, 16, 10], [20, 17, 15]]), 'hello there')
208 'tfjflpznvyac'
209 </code></pre></div>
210 <details class="source">
211 <summary>
212 <span>Expand source code</span>
213 </summary>
214 <pre><code class="python">def hill_encipher(matrix, message_letters, fillvalue=&#39;a&#39;):
215 &#34;&#34;&#34;Hill cipher
216
217 &gt;&gt;&gt; hill_encipher(np.matrix([[7,8], [11,11]]), &#39;hellothere&#39;)
218 &#39;drjiqzdrvx&#39;
219 &gt;&gt;&gt; hill_encipher(np.matrix([[6, 24, 1], [13, 16, 10], [20, 17, 15]]), \
220 &#39;hello there&#39;)
221 &#39;tfjflpznvyac&#39;
222 &#34;&#34;&#34;
223 n = len(matrix)
224 sanitised_message = sanitise(message_letters)
225 if len(sanitised_message) % n != 0:
226 padding = fillvalue[0] * (n - len(sanitised_message) % n)
227 else:
228 padding = &#39;&#39;
229 message = [pos(c) for c in sanitised_message + padding]
230 message_chunks = [message[i:i+n] for i in range(0, len(message), n)]
231 # message_chunks = chunks(message, len(matrix), fillvalue=None)
232 enciphered_chunks = [((matrix * np.matrix(c).T).T).tolist()[0]
233 for c in message_chunks]
234 return cat([unpos(round(l))
235 for l in sum(enciphered_chunks, [])])</code></pre>
236 </details>
237 </dd>
238 <dt id="szyfrow.hill.lcat"><code class="name flex">
239 <span>def <span class="ident">lcat</span></span>(<span>iterable, /)</span>
240 </code></dt>
241 <dd>
242 <div class="desc"><p>Concatenate any number of strings.</p>
243 <p>The string whose method is called is inserted in between each given string.
244 The result is returned as a new string.</p>
245 <p>Example: '.'.join(['ab', 'pq', 'rs']) -&gt; 'ab.pq.rs'</p></div>
246 </dd>
247 <dt id="szyfrow.hill.wcat"><code class="name flex">
248 <span>def <span class="ident">wcat</span></span>(<span>iterable, /)</span>
249 </code></dt>
250 <dd>
251 <div class="desc"><p>Concatenate any number of strings.</p>
252 <p>The string whose method is called is inserted in between each given string.
253 The result is returned as a new string.</p>
254 <p>Example: '.'.join(['ab', 'pq', 'rs']) -&gt; 'ab.pq.rs'</p></div>
255 </dd>
256 </dl>
257 </section>
258 <section>
259 </section>
260 </article>
261 <nav id="sidebar">
262 <h1>Index</h1>
263 <div class="toc">
264 <ul></ul>
265 </div>
266 <ul id="index">
267 <li><h3>Super-module</h3>
268 <ul>
269 <li><code><a title="szyfrow" href="index.html">szyfrow</a></code></li>
270 </ul>
271 </li>
272 <li><h3><a href="#header-functions">Functions</a></h3>
273 <ul class="two-column">
274 <li><code><a title="szyfrow.hill.cat" href="#szyfrow.hill.cat">cat</a></code></li>
275 <li><code><a title="szyfrow.hill.hill_break" href="#szyfrow.hill.hill_break">hill_break</a></code></li>
276 <li><code><a title="szyfrow.hill.hill_break_worker" href="#szyfrow.hill.hill_break_worker">hill_break_worker</a></code></li>
277 <li><code><a title="szyfrow.hill.hill_decipher" href="#szyfrow.hill.hill_decipher">hill_decipher</a></code></li>
278 <li><code><a title="szyfrow.hill.hill_encipher" href="#szyfrow.hill.hill_encipher">hill_encipher</a></code></li>
279 <li><code><a title="szyfrow.hill.lcat" href="#szyfrow.hill.lcat">lcat</a></code></li>
280 <li><code><a title="szyfrow.hill.wcat" href="#szyfrow.hill.wcat">wcat</a></code></li>
281 </ul>
282 </li>
283 </ul>
284 </nav>
285 </main>
286 <footer id="footer">
287 <p>Generated by <a href="https://pdoc3.github.io/pdoc"><cite>pdoc</cite> 0.9.1</a>.</p>
288 </footer>
289 </body>
290 </html>