sofic 0.1.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (150) hide show
  1. sofic/__init__.py +185 -0
  2. sofic/automata/__init__.py +207 -0
  3. sofic/automata/_config_simulation.py +40 -0
  4. sofic/automata/active.py +611 -0
  5. sofic/automata/alergia.py +222 -0
  6. sofic/automata/algorithms.py +376 -0
  7. sofic/automata/atomaton.py +58 -0
  8. sofic/automata/base.py +161 -0
  9. sofic/automata/buchi.py +23 -0
  10. sofic/automata/buchi_simulation.py +67 -0
  11. sofic/automata/canonical_dual.py +18 -0
  12. sofic/automata/canonical_extraction.py +122 -0
  13. sofic/automata/dfa.py +85 -0
  14. sofic/automata/dfasat.py +195 -0
  15. sofic/automata/edsm.py +219 -0
  16. sofic/automata/enumeration.py +44 -0
  17. sofic/automata/icdfa.py +421 -0
  18. sofic/automata/idfa.py +363 -0
  19. sofic/automata/languages/__init__.py +39 -0
  20. sofic/automata/languages/_quotient_utils.py +64 -0
  21. sofic/automata/languages/atoms.py +31 -0
  22. sofic/automata/languages/automaton_ops.py +243 -0
  23. sofic/automata/languages/base.py +67 -0
  24. sofic/automata/languages/operations.py +78 -0
  25. sofic/automata/languages/quotients.py +66 -0
  26. sofic/automata/languages/residuals.py +25 -0
  27. sofic/automata/learning.py +79 -0
  28. sofic/automata/nfa.py +39 -0
  29. sofic/automata/nwa.py +343 -0
  30. sofic/automata/nwa_simulation.py +56 -0
  31. sofic/automata/observation.py +40 -0
  32. sofic/automata/papni.py +301 -0
  33. sofic/automata/regex.py +128 -0
  34. sofic/automata/rfsa.py +35 -0
  35. sofic/automata/rpni.py +193 -0
  36. sofic/automata/subsequential.py +201 -0
  37. sofic/automata/transducer_operations.py +350 -0
  38. sofic/automata/transducer_simulation.py +150 -0
  39. sofic/automata/transducers.py +365 -0
  40. sofic/automata/unifilar.py +107 -0
  41. sofic/automata/vpa.py +1373 -0
  42. sofic/automata/vpa_simulation.py +53 -0
  43. sofic/base.py +153 -0
  44. sofic/core.py +47 -0
  45. sofic/examples/__init__.py +86 -0
  46. sofic/examples/epsilon_machines.py +1089 -0
  47. sofic/examples/processes.py +1491 -0
  48. sofic/examples/shifts.py +144 -0
  49. sofic/exceptions.py +33 -0
  50. sofic/generators/__init__.py +115 -0
  51. sofic/generators/_word_measures.py +94 -0
  52. sofic/generators/alternative_complexity.py +104 -0
  53. sofic/generators/base.py +327 -0
  54. sofic/generators/bidirectional_construction.py +717 -0
  55. sofic/generators/bidirectional_epsilon_machine.py +689 -0
  56. sofic/generators/block_convergence.py +668 -0
  57. sofic/generators/block_entropy.py +578 -0
  58. sofic/generators/channel_measures.py +75 -0
  59. sofic/generators/conversions.py +182 -0
  60. sofic/generators/directional_flow.py +245 -0
  61. sofic/generators/edge_emissions.py +36 -0
  62. sofic/generators/edge_machine.py +178 -0
  63. sofic/generators/epsilon_construction.py +193 -0
  64. sofic/generators/epsilon_inference.py +703 -0
  65. sofic/generators/epsilon_machine.py +557 -0
  66. sofic/generators/epsilon_transducer.py +168 -0
  67. sofic/generators/epsilon_transducer_construction.py +185 -0
  68. sofic/generators/epsilon_transducer_inference.py +499 -0
  69. sofic/generators/hmm_inference.py +719 -0
  70. sofic/generators/information_diagram.py +428 -0
  71. sofic/generators/lumping.py +447 -0
  72. sofic/generators/markov.py +100 -0
  73. sofic/generators/mealy.py +156 -0
  74. sofic/generators/measures.py +257 -0
  75. sofic/generators/minimal_generative_model.py +821 -0
  76. sofic/generators/mixed_state.py +250 -0
  77. sofic/generators/mixed_state_construction.py +163 -0
  78. sofic/generators/moore.py +75 -0
  79. sofic/generators/nmachine.py +78 -0
  80. sofic/generators/nmachine_construction.py +70 -0
  81. sofic/generators/pfa.py +100 -0
  82. sofic/generators/prob.py +291 -0
  83. sofic/generators/process_equivalence.py +207 -0
  84. sofic/generators/quasi_inference.py +74 -0
  85. sofic/generators/quasi_realization.py +97 -0
  86. sofic/generators/reversal.py +66 -0
  87. sofic/generators/stack_hmm.py +426 -0
  88. sofic/generators/stack_inference.py +509 -0
  89. sofic/generators/stationary.py +134 -0
  90. sofic/generators/stochastic.py +65 -0
  91. sofic/generators/synchronization.py +407 -0
  92. sofic/generators/topological_epsilon_enumeration.py +349 -0
  93. sofic/generators/words.py +226 -0
  94. sofic/graph.py +135 -0
  95. sofic/indexing.py +31 -0
  96. sofic/inference/__init__.py +45 -0
  97. sofic/inference/bayesian/__init__.py +68 -0
  98. sofic/inference/bayesian/comparison.py +199 -0
  99. sofic/inference/bayesian/counts.py +219 -0
  100. sofic/inference/bayesian/diversity.py +254 -0
  101. sofic/inference/bayesian/epsilon.py +270 -0
  102. sofic/inference/bayesian/hdp_hmm.py +340 -0
  103. sofic/inference/bayesian/markov.py +294 -0
  104. sofic/inference/bayesian/pymc_backend.py +71 -0
  105. sofic/inference/bayesian/stack_hmm.py +215 -0
  106. sofic/inference/model_selection.py +365 -0
  107. sofic/inference/spectral.py +564 -0
  108. sofic/operations.py +16 -0
  109. sofic/properties.py +339 -0
  110. sofic/serialization.py +450 -0
  111. sofic/shifts/__init__.py +48 -0
  112. sofic/shifts/algorithms.py +84 -0
  113. sofic/shifts/base.py +49 -0
  114. sofic/shifts/cover_construction.py +76 -0
  115. sofic/shifts/covers.py +47 -0
  116. sofic/shifts/dyck_algorithms.py +100 -0
  117. sofic/shifts/dyck_enumeration.py +275 -0
  118. sofic/shifts/markov_dyck.py +172 -0
  119. sofic/shifts/parry_construction.py +82 -0
  120. sofic/shifts/sft.py +104 -0
  121. sofic/shifts/sft_construction.py +52 -0
  122. sofic/shifts/sliding_block_code.py +156 -0
  123. sofic/shifts/sofic.py +111 -0
  124. sofic/shifts/sofic_dyck.py +110 -0
  125. sofic/shifts/sofic_relation.py +64 -0
  126. sofic/shifts/textile.py +104 -0
  127. sofic/shifts/tmc.py +46 -0
  128. sofic/shifts/tmc_construction.py +58 -0
  129. sofic/shifts/topological_anatomy.py +150 -0
  130. sofic/states.py +27 -0
  131. sofic/testing/__init__.py +8 -0
  132. sofic/testing/strategies.py +154 -0
  133. sofic/viz/__init__.py +16 -0
  134. sofic/viz/_context.py +345 -0
  135. sofic/viz/_edge.py +216 -0
  136. sofic/viz/_format.py +89 -0
  137. sofic/viz/_labels.py +34 -0
  138. sofic/viz/_names.py +17 -0
  139. sofic/viz/_rational.py +20 -0
  140. sofic/viz/_tikz_compile.py +177 -0
  141. sofic/viz/_tikz_format.py +122 -0
  142. sofic/viz/_tikz_layout.py +218 -0
  143. sofic/viz/assets/vaucanson.tikz +71 -0
  144. sofic/viz/graphviz.py +158 -0
  145. sofic/viz/idiagram.py +350 -0
  146. sofic/viz/tikz.py +381 -0
  147. sofic-0.1.0.dist-info/METADATA +444 -0
  148. sofic-0.1.0.dist-info/RECORD +150 -0
  149. sofic-0.1.0.dist-info/WHEEL +4 -0
  150. sofic-0.1.0.dist-info/licenses/LICENSE.txt +29 -0
@@ -0,0 +1,444 @@
1
+ Metadata-Version: 2.5
2
+ Name: sofic
3
+ Version: 0.1.0
4
+ Summary: Python package for hidden Markov models, symbolic dynamics, finite state machines, and stochastic symbol generators.
5
+ Project-URL: Homepage, https://github.com/dit/sofic
6
+ Project-URL: Repository, https://github.com/dit/sofic
7
+ Project-URL: Documentation, https://sofic.readthedocs.io
8
+ Author-email: chebee7i <admin@dit.io>, "Ryan G. James" <dit@autoplectic.com>
9
+ License-Expression: BSD-3-Clause
10
+ License-File: LICENSE.txt
11
+ Classifier: Intended Audience :: Science/Research
12
+ Classifier: License :: OSI Approved :: BSD License
13
+ Classifier: Programming Language :: Python :: 3.11
14
+ Classifier: Programming Language :: Python :: 3.12
15
+ Classifier: Programming Language :: Python :: 3.13
16
+ Classifier: Programming Language :: Python :: 3.14
17
+ Classifier: Topic :: Scientific/Engineering
18
+ Classifier: Topic :: Scientific/Engineering :: Mathematics
19
+ Classifier: Topic :: Scientific/Engineering :: Physics
20
+ Requires-Python: >=3.11
21
+ Requires-Dist: dit>=2.2
22
+ Requires-Dist: networkx>=2.6
23
+ Requires-Dist: numpy>=1.22
24
+ Requires-Dist: pyyaml>=6.0
25
+ Requires-Dist: scipy>=1.7
26
+ Provides-Extra: bayes
27
+ Requires-Dist: arviz; extra == 'bayes'
28
+ Requires-Dist: pymc>=5; extra == 'bayes'
29
+ Provides-Extra: dev
30
+ Requires-Dist: dit[symbolic]>=2.2; extra == 'dev'
31
+ Requires-Dist: graphviz>=0.20; extra == 'dev'
32
+ Requires-Dist: hypothesis>=6.0; extra == 'dev'
33
+ Requires-Dist: hypothesis[numpy]; extra == 'dev'
34
+ Requires-Dist: ipython; extra == 'dev'
35
+ Requires-Dist: matplotlib; extra == 'dev'
36
+ Requires-Dist: matplotlib>=3.5; extra == 'dev'
37
+ Requires-Dist: pytest-cov; extra == 'dev'
38
+ Requires-Dist: pytest-rerunfailures; extra == 'dev'
39
+ Requires-Dist: pytest-sugar; extra == 'dev'
40
+ Requires-Dist: pytest-xdist; extra == 'dev'
41
+ Requires-Dist: pytest>=9.0.3; extra == 'dev'
42
+ Requires-Dist: ruff; extra == 'dev'
43
+ Requires-Dist: sphinx; extra == 'dev'
44
+ Requires-Dist: sphinx-rtd-theme; extra == 'dev'
45
+ Requires-Dist: sphinxcontrib-bibtex; extra == 'dev'
46
+ Requires-Dist: sympy>=1.12; extra == 'dev'
47
+ Requires-Dist: ty; extra == 'dev'
48
+ Provides-Extra: docs
49
+ Requires-Dist: dit[symbolic]>=2.2; extra == 'docs'
50
+ Requires-Dist: ipython; extra == 'docs'
51
+ Requires-Dist: matplotlib; extra == 'docs'
52
+ Requires-Dist: sphinx; extra == 'docs'
53
+ Requires-Dist: sphinx-rtd-theme; extra == 'docs'
54
+ Requires-Dist: sphinxcontrib-bibtex; extra == 'docs'
55
+ Requires-Dist: sympy>=1.12; extra == 'docs'
56
+ Provides-Extra: sat
57
+ Requires-Dist: python-sat>=1.8; extra == 'sat'
58
+ Provides-Extra: symbolic
59
+ Requires-Dist: dit[symbolic]>=2.2; extra == 'symbolic'
60
+ Requires-Dist: sympy>=1.12; extra == 'symbolic'
61
+ Provides-Extra: test
62
+ Requires-Dist: graphviz>=0.20; extra == 'test'
63
+ Requires-Dist: hypothesis>=6.0; extra == 'test'
64
+ Requires-Dist: hypothesis[numpy]; extra == 'test'
65
+ Requires-Dist: pytest-cov; extra == 'test'
66
+ Requires-Dist: pytest-rerunfailures; extra == 'test'
67
+ Requires-Dist: pytest-sugar; extra == 'test'
68
+ Requires-Dist: pytest-xdist; extra == 'test'
69
+ Requires-Dist: pytest>=9.0.3; extra == 'test'
70
+ Provides-Extra: viz
71
+ Requires-Dist: graphviz>=0.20; extra == 'viz'
72
+ Requires-Dist: matplotlib>=3.5; extra == 'viz'
73
+ Description-Content-Type: text/x-rst
74
+
75
+ =======
76
+ sofic
77
+ =======
78
+
79
+ ``sofic`` is a Python package for hidden Markov models, symbolic dynamics,
80
+ finite state machines, and other stochastic symbol generators.
81
+
82
+ Basic Information
83
+ -----------------
84
+
85
+ Documentation
86
+ ~~~~~~~~~~~~~~
87
+
88
+ https://sofic.readthedocs.io
89
+
90
+ Repository
91
+ ~~~~~~~~~~
92
+
93
+ https://github.com/dit/sofic
94
+
95
+ Dependencies
96
+ ~~~~~~~~~~~~
97
+
98
+ * Python 3.11+
99
+ * `networkx <https://networkx.github.io/>`_
100
+ * `numpy <http://www.numpy.org/>`_
101
+ * `scipy <https://www.scipy.org/>`_
102
+ * `pyyaml <https://pyyaml.org/>`_
103
+ * `dit <https://github.com/dit/dit>`_ (information-theoretic measures)
104
+
105
+ Development
106
+ ~~~~~~~~~~~
107
+
108
+ Clone the repository and install development dependencies with ``uv``:
109
+
110
+ .. code-block:: bash
111
+
112
+ git clone https://github.com/dit/sofic.git
113
+ cd sofic
114
+ uv sync --extra dev
115
+
116
+ Run tests with ``uv run pytest``. See the ``generalinfo`` page in the Sphinx
117
+ docs for linting, type checking, and documentation builds.
118
+
119
+ Introduction
120
+ ------------
121
+
122
+ Many natural and engineered processes produce sequences of symbols whose
123
+ statistics are governed by latent structure: hidden states, transition rules,
124
+ or algebraic constraints on allowed paths. ``sofic`` collects algorithms and
125
+ data structures for representing, simulating, and analyzing such generators
126
+ behind a single, composable Python API.
127
+
128
+ Every model is a graph-backed state machine, so the same objects support
129
+ construction, validation, simulation, visualization, (de)serialization, and a
130
+ large library of structural and information-theoretic measures. The three
131
+ main families are:
132
+
133
+ * **Stochastic generators** (``sofic.generators``) — Markov chains, hidden
134
+ Markov models (Moore and Mealy presentations), ε-machines, probabilistic
135
+ finite automata, mixed-state presentations, and quasiprobabilistic
136
+ generators. These assign probabilities to sequences.
137
+ * **Finite automata** (``sofic.automata``) — DFAs, NFAs, transducers
138
+ (Mealy/Moore machines), regular languages, Büchi automata, visibly pushdown
139
+ and nested-word automata, and residual finite-state automata. These recognize
140
+ or transform languages.
141
+ * **Symbolic shifts** (``sofic.shifts``) — shifts of finite type, sofic
142
+ shifts, topological Markov chains, and Dyck/sofic-Dyck shifts. These describe
143
+ the *support* (set of allowed sequences) of a process.
144
+
145
+ The package builds on NumPy, SciPy, and NetworkX and is designed to sit
146
+ alongside the `dit <https://github.com/dit/dit>`_ ecosystem for
147
+ information-theoretic analysis of the processes these models describe.
148
+
149
+ Installation
150
+ ------------
151
+
152
+ .. code-block:: bash
153
+
154
+ pip install sofic
155
+
156
+ Optional extras:
157
+
158
+ * ``sofic[viz]`` — Graphviz diagrams in terminals and Jupyter
159
+ * ``sofic[bayes]`` — PyMC/ArviZ backends for Bayesian inference
160
+ * ``sofic[test]`` — pytest, hypothesis, and graphviz for the test suite
161
+ * ``sofic[docs]`` — Sphinx, IPython, and matplotlib for the docs
162
+ * ``sofic[dev]`` — linting, type checking, docs, and all of the above
163
+
164
+ Quickstart
165
+ ----------
166
+
167
+ The basic workflow is the same for every model: build (or load) a generator,
168
+ call ``validate()``, then compute properties or convert to another
169
+ presentation. States can be any hashable object and every model exposes
170
+ ``states()``, ``transitions()``, ``draw()``, and ``to_yaml()``.
171
+
172
+ Stochastic generators
173
+ ~~~~~~~~~~~~~~~~~~~~~~~
174
+
175
+ **Markov chain** — a visible-state process. Edges carry ``P(target | source)``:
176
+
177
+ .. code-block:: python
178
+
179
+ from sofic import MarkovChain
180
+
181
+ mc = MarkovChain(initial_distribution={"sunny": 0.5, "rainy": 0.5})
182
+ mc.add_transition("sunny", "sunny", 0.9)
183
+ mc.add_transition("sunny", "rainy", 0.1)
184
+ mc.add_transition("rainy", "sunny", 0.5)
185
+ mc.add_transition("rainy", "rainy", 0.5)
186
+ mc.validate()
187
+
188
+ mc.stationary_distribution() # array([0.8333, 0.1667])
189
+ mc.entropy_rate() # 0.5575 bits/symbol
190
+ mc.is_deterministic() # False
191
+
192
+ **Moore HMM** — hidden states with an emission law ``P(observation | state)`` on
193
+ states and ``P(target | source)`` on edges:
194
+
195
+ .. code-block:: python
196
+
197
+ from sofic import MooreHMM
198
+
199
+ moore = MooreHMM(
200
+ observation_alphabet=frozenset({"H", "T"}),
201
+ initial_distribution={0: 0.5, 1: 0.5},
202
+ )
203
+ moore.add_transition(0, 0, 0.5)
204
+ moore.add_transition(0, 1, 0.5)
205
+ moore.add_transition(1, 0, 0.5)
206
+ moore.add_transition(1, 1, 0.5)
207
+ moore.set_emission_distribution(0, {"H": 0.9, "T": 0.1})
208
+ moore.set_emission_distribution(1, {"H": 0.1, "T": 0.9})
209
+ moore.validate()
210
+
211
+ moore.stationary_distribution() # array([0.5, 0.5])
212
+ moore.log_likelihood(["H", "H", "T", "T"]) # -2.7726 (log2)
213
+ observations, hidden = moore.sample(6) # simulate the process
214
+
215
+ **Mealy HMM** — hidden states with a joint transition/emission law
216
+ ``P(target, symbol | source)`` on edges. Here is the golden-mean process
217
+ (consecutive ``1``\ s are forbidden):
218
+
219
+ .. code-block:: python
220
+
221
+ from sofic import MealyHMM
222
+
223
+ gm = MealyHMM(
224
+ observation_alphabet=frozenset({0, 1}),
225
+ initial_distribution={"A": 2 / 3, "B": 1 / 3},
226
+ )
227
+ gm.add_transition("A", "A", 0, 0.5) # source, target, symbol, probability
228
+ gm.add_transition("A", "B", 1, 0.5)
229
+ gm.add_transition("B", "A", 0, 1.0)
230
+ gm.validate()
231
+
232
+ gm.entropy_rate() # 0.6667 bits/symbol
233
+ gm.is_unifilar() # True
234
+ gm.word_probability([1, 0, 1]) # 0.1667
235
+
236
+ Many canonical models ship in ``sofic.examples``, so the golden mean is
237
+ also just ``from sofic.examples import golden_mean; gm = golden_mean(0.5)``.
238
+
239
+ **ε-machine** — the minimal unifilar (causal-state) presentation of a stationary
240
+ process. Build one from any HMM, from an observed sequence, or directly, and
241
+ read off computational-mechanics quantities:
242
+
243
+ .. code-block:: python
244
+
245
+ from sofic import EpsilonMachine
246
+
247
+ eps = EpsilonMachine.from_hmm(gm) # minimize an HMM presentation
248
+ # eps = EpsilonMachine.from_sequence(data, method="cssr", Lmax=4) # infer
249
+ # eps = EpsilonMachine.from_sequence(data, method="spectral", prefix_length=3, rank=2)
250
+
251
+ eps.statistical_complexity() # 0.9183 bits (C_mu)
252
+ eps.entropy_rate() # 0.6667 bits/symbol (h_mu)
253
+ eps.markov_order() # 1
254
+ eps.cryptic_order() # 1
255
+
256
+ Finite automata
257
+ ~~~~~~~~~~~~~~~
258
+
259
+ **DFA** — a deterministic recognizer. This one accepts strings with an even
260
+ number of ``b``\ s (states are added before their transitions so determinism can
261
+ be checked as you go):
262
+
263
+ .. code-block:: python
264
+
265
+ from sofic import DFA
266
+
267
+ dfa = DFA(
268
+ input_alphabet=frozenset({"a", "b"}),
269
+ initial_states=frozenset({"even"}),
270
+ accepting_states=frozenset({"even"}),
271
+ )
272
+ dfa.graph.add_state("even")
273
+ dfa.graph.add_state("odd")
274
+ dfa.add_transition("even", "even", "a")
275
+ dfa.add_transition("even", "odd", "b")
276
+ dfa.add_transition("odd", "odd", "a")
277
+ dfa.add_transition("odd", "even", "b")
278
+ dfa.validate()
279
+
280
+ dfa.recognizes("abba") # True (two b's)
281
+ dfa.recognizes("abbb") # False (three b's)
282
+ dfa.minimize() # DFA(2 states, 4 transitions)
283
+ dfa.to_regex() # 'a*|a*b(?:...)*ba*'
284
+
285
+ **NFA** — nondeterministic, with first-class ε-transitions. Determinize to a DFA
286
+ when you need one:
287
+
288
+ .. code-block:: python
289
+
290
+ from sofic import NFA
291
+
292
+ nfa = NFA(
293
+ input_alphabet=frozenset({"a", "b"}),
294
+ initial_states=frozenset({"q0"}),
295
+ accepting_states=frozenset({"q2"}),
296
+ )
297
+ nfa.add_transition("q0", "q0", "a")
298
+ nfa.add_transition("q0", "q0", "b")
299
+ nfa.add_transition("q0", "q1", "a")
300
+ nfa.add_transition("q1", "q2", "b")
301
+ nfa.validate()
302
+
303
+ nfa.recognizes("ab") # True
304
+ dfa = nfa.determinize()
305
+
306
+ **Transducer (Mealy machine)** — maps input words to output words. This one
307
+ inverts bits:
308
+
309
+ .. code-block:: python
310
+
311
+ from sofic import MealyMachine
312
+
313
+ inv = MealyMachine(
314
+ input_alphabet=frozenset({"0", "1"}),
315
+ output_alphabet=frozenset({"0", "1"}),
316
+ initial_states=frozenset({"q"}),
317
+ )
318
+ inv.add_transition("q", "q", "0", "1") # source, target, input, output
319
+ inv.add_transition("q", "q", "1", "0")
320
+ inv.validate()
321
+
322
+ inv.transduce("0110") # {('1', '0', '0', '1')}
323
+
324
+ All automata also support ``union``, ``intersection``, ``complement``,
325
+ ``difference``, ``concat``, and ``kleene_star`` (see the
326
+ ``LabeledAutomaton`` base class).
327
+
328
+ Symbolic shifts
329
+ ~~~~~~~~~~~~~~~
330
+
331
+ **Shift of finite type** — the set of sequences avoiding a finite list of
332
+ forbidden words. The golden-mean shift forbids ``11``:
333
+
334
+ .. code-block:: python
335
+
336
+ from sofic import ShiftOfFiniteType
337
+
338
+ sft = ShiftOfFiniteType.from_forbidden_words(
339
+ {("1", "1")},
340
+ symbol_alphabet=frozenset({"0", "1"}),
341
+ )
342
+ sft.validate()
343
+
344
+ sft.forbidden_words() # frozenset({('1', '1')})
345
+ sorted(sft.factor_language(3)) # allowed length-3 words
346
+ sft.is_unifilar() # True (right-resolving presentation)
347
+
348
+ **Topological Markov chain** — an adjacency-matrix presentation; compute the
349
+ topological entropy or extract the measure of maximal entropy:
350
+
351
+ .. code-block:: python
352
+
353
+ import numpy as np
354
+ from sofic import TopologicalMarkovChain
355
+
356
+ tmc = TopologicalMarkovChain.from_adjacency(
357
+ np.array([[1, 1], [1, 0]], dtype=float), # golden-mean adjacency
358
+ symbol_alphabet=frozenset({0, 1}),
359
+ )
360
+ tmc.validate()
361
+
362
+ tmc.topological_entropy() # 0.4812 (ln of the golden ratio)
363
+ tmc.parry_measure() # MealyHMM at maximal entropy
364
+
365
+ **Sofic shift** — a labeled-graph presentation (the shift-space analog of an
366
+ NFA). This is the even shift (even-length runs of ``0`` between ``1``\ s):
367
+
368
+ .. code-block:: python
369
+
370
+ from sofic import SoficShift
371
+
372
+ even = SoficShift(symbol_alphabet=frozenset({0, 1}))
373
+ even.add_transition("even", "even", 0)
374
+ even.add_transition("even", "odd", 1)
375
+ even.add_transition("odd", "even", 1)
376
+ even.validate()
377
+
378
+ even.topological_entropy() # 0.4812
379
+
380
+ Converting between model types
381
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
382
+
383
+ The presentations are related by a web of conversions. Probabilistic models can
384
+ drop their weights to become automata or shifts (keeping only their support);
385
+ HMMs can be minimized to ε-machines; automata can be determinized, minimized,
386
+ and turned into regular expressions:
387
+
388
+ .. code-block:: python
389
+
390
+ # Between stochastic presentations
391
+ gm.to_mealy() # any HMM -> Mealy HMM
392
+ moore.to_mealy() # Moore -> Mealy (joint edge law)
393
+ EpsilonMachine.from_hmm(gm) # HMM -> minimal causal ε-machine
394
+ eps.to_bidirectional() # ε-machine -> bidirectional presentation
395
+ eps.mixed_state_presentation() # -> observer belief-state dynamics
396
+ EpsilonMachine.from_time_reversed(eps) # forward -> reverse ε-machine
397
+
398
+ # Stochastic -> topological (drop probabilities, keep the support)
399
+ gm.to_sofic_shift() # HMM support as a sofic shift
400
+ gm.to_support_nfa() # HMM support as an NFA
401
+ gm.to_support_dfa() # HMM support as a (determinized) DFA
402
+
403
+ # Between automata
404
+ nfa.determinize() # NFA -> DFA
405
+ DFA.from_nfa(nfa) # NFA -> DFA (same result)
406
+ dfa.minimize() # DFA -> minimal DFA
407
+ dfa.to_regex() # automaton -> regular expression
408
+
409
+ # Between / out of shifts
410
+ tmc.to_sofic_shift() # topological Markov chain -> sofic shift
411
+ tmc.parry_measure() # shift -> max-entropy MealyHMM
412
+ sofic.parry_measure() # sofic shift -> max-entropy MealyHMM
413
+
414
+ Every model can also be round-tripped through YAML:
415
+
416
+ .. code-block:: python
417
+
418
+ text = eps.to_yaml()
419
+ restored = EpsilonMachine.from_yaml(text)
420
+ # or: sofic.model_to_yaml(eps) / sofic.model_from_yaml(text)
421
+
422
+ Information anatomy (advanced)
423
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
424
+
425
+ With ``dit`` installed, a bidirectional ε-machine exposes the full stored- and
426
+ transient-information anatomy of a process (James, Burke & Crutchfield, 2013):
427
+
428
+ .. code-block:: python
429
+
430
+ from sofic.examples import golden_mean_bidirectional, tent_map_misiurewicz_bidirectional
431
+
432
+ bidir = golden_mean_bidirectional(0.5)
433
+ bidir.statistical_complexity() # 1.5850 bits (C±)
434
+ bidir.excess_entropy() # 0.2516 bits (E)
435
+ bidir.crypticity() # 1.3333 bits (chi = C± - E)
436
+
437
+ tent = tent_map_misiurewicz_bidirectional()
438
+ tent.information_anatomy() # {'rho_mu', 'bound_mu', 'ephemeral_mu',
439
+ # 'entropy_rate', 'excess_entropy', 'crypticity'}
440
+
441
+ License
442
+ -------
443
+
444
+ ``sofic`` is distributed under the BSD 3-Clause License; see ``LICENSE.txt``.
@@ -0,0 +1,150 @@
1
+ sofic/__init__.py,sha256=ii_13tOCVcdvHgA3voyBZ7I3IpyPEsFsbjHbXPliPT4,4290
2
+ sofic/base.py,sha256=DwRUWcbDWBrWo3rfFbVCOMk3RoAmhrp7B_-S1YA_TdA,5168
3
+ sofic/core.py,sha256=uEfilrMfffm-T13HguUQxPKmcl_m3YnYFbj52rwHr88,920
4
+ sofic/exceptions.py,sha256=0WKAdfta__X45nnblGJnl-kt4Y4NEI-tEoZVPHXPMBo,921
5
+ sofic/graph.py,sha256=5oomNKxMTreqNfa9EyKZgqlv4d3i0DfL7xJMkWSe7SA,4491
6
+ sofic/indexing.py,sha256=Peb4QdjeoUAFSgn7OmOqTNR61-ZOKpJwtataZUjMBOg,861
7
+ sofic/operations.py,sha256=bM-qyRJbx6lDEMCp-eZZEGH3Ynj_IPFNDHKKMJzTGzE,594
8
+ sofic/properties.py,sha256=cROWDN6PB7AoDK-Di1lpIOyuc165pyMsRCBdbsx3jwg,12538
9
+ sofic/serialization.py,sha256=PsgU3KIVDN3SRkoM6QkUJ38sFVTmOv-o7nRHPeCbrRM,17585
10
+ sofic/states.py,sha256=NnsEaHsKW8qzuFA1x2XV7WeD4OQeBY_du410RTQfxqQ,1111
11
+ sofic/automata/__init__.py,sha256=K3Wom17IgiIQ3DU8Z6LsCjoPW6vFAxje0f-kWwV59VI,5653
12
+ sofic/automata/_config_simulation.py,sha256=OFdq6E_wM9Ih8WuDmvScPlBUvRRi8R_qffvQHhGFm9c,1480
13
+ sofic/automata/active.py,sha256=bryUzkVIN_oGJA70OqwUsE0uzq4K3R7cL7WAPHLBB5g,21549
14
+ sofic/automata/alergia.py,sha256=vHEhb_SN_yjsMfA8b_EYEtmLESDHBh_rVVTK7VfCAug,7862
15
+ sofic/automata/algorithms.py,sha256=xuqFRoy7tP4A_HKDQX1ANNTOlUz8JAPIV1a1ZYoYKA8,13759
16
+ sofic/automata/atomaton.py,sha256=AjUKU9b5yihzHH0EGVrkUPv2DlmEshSBiq6-jCHNRmM,1993
17
+ sofic/automata/base.py,sha256=TAXN3hhDOEkPDAfrMAc2G1-6Mc1ScQIbYyZDcnBfGTk,6371
18
+ sofic/automata/buchi.py,sha256=VnfC-11nTj_Swf_vyLXocJyxJC5wJprU17ab8Z9VXlw,794
19
+ sofic/automata/buchi_simulation.py,sha256=orCoeF199Nl7YxKRF0-r1rgz8vcNKAuS29_Xlogr3-4,2246
20
+ sofic/automata/canonical_dual.py,sha256=3-1rZBCAIuSQMgxpWB05GK_QpLv7nS5X7R7jmkzzjG8,661
21
+ sofic/automata/canonical_extraction.py,sha256=dvp85XAlfMN4fXszp9QZscy4ejmtsOoW3OLn6u21hpY,4551
22
+ sofic/automata/dfa.py,sha256=jzhe7QsweQQsI6fJx1qkDWS4V7KPSB3PvrZhDrIC4fk,3207
23
+ sofic/automata/dfasat.py,sha256=cTuePqzPffX5hTZ5KmJCiX9Bwl3BtBUKGaeY5izsv30,6549
24
+ sofic/automata/edsm.py,sha256=6M1Ux45sQP0zRmXxbCoynjsiVYVrjIRmA8Iv7mnspYc,7352
25
+ sofic/automata/enumeration.py,sha256=77Th5HlQkPWScAkx8UYKsxPnZjN272MpwxxC6OiMGbM,1369
26
+ sofic/automata/icdfa.py,sha256=neEIMajs66DWTSBvglroZ-8bjg_azERPVM8ZkEDAzW0,14164
27
+ sofic/automata/idfa.py,sha256=wKxC4CKrEoDLG_-8zV758ujhR4uehpG_rYUBKfs118I,12006
28
+ sofic/automata/learning.py,sha256=o6zUz92ia5vOZGXyAztR_I6XO7jYy4bxk4Ll0VgmG5Y,2660
29
+ sofic/automata/nfa.py,sha256=FWCkKGJhPAXtOopAvNnYmdbQK2OxfxD6ZcqcRPh5e1I,1313
30
+ sofic/automata/nwa.py,sha256=Jk6yIRAClh6R75-oHcj3cOdr32dWX3b6poCuToW0hSE,14990
31
+ sofic/automata/nwa_simulation.py,sha256=7rE-bfBvLlPDGyOIwNaR-AZ3Q8JGJJelhr06LVYgqp4,2101
32
+ sofic/automata/observation.py,sha256=rdn9-rW2C6wxSc07u8DkuOPPJZptElSo6nqXKsNJzqI,1497
33
+ sofic/automata/papni.py,sha256=-zcfpMBQlwD2Rz5V-4bX1BHs788jSOAcxewYfPK9Mdc,11113
34
+ sofic/automata/regex.py,sha256=iskKWngd593Afo6CObTrD4qeCHzrTF_8kpvp5P7Tl54,4088
35
+ sofic/automata/rfsa.py,sha256=eGWwnv3BJJDiTfTOny-ERi2Z3ggW22PXSXbExwoIIew,1159
36
+ sofic/automata/rpni.py,sha256=bFjaUvlH4PBlk-O3gN79jpfRmonVWesLyFHnTUFIiF0,6384
37
+ sofic/automata/subsequential.py,sha256=E2ntA4v1ZlrPZyDVoIAxVzdPV0BHvr_RpfII6TRMviw,8248
38
+ sofic/automata/transducer_operations.py,sha256=YV8dS5iy_rxFzvmMlCEJN3LnN7JEdG49chyxKxM8kQQ,14125
39
+ sofic/automata/transducer_simulation.py,sha256=9LEvV7BzMyes6ymJPaFqPi3qZi-z7XLY8TLbxeHdGQI,5609
40
+ sofic/automata/transducers.py,sha256=cbYfDtIYSc7OVBnEqkWZPBn5eJTWKFRWFHaxAWEfc2k,15178
41
+ sofic/automata/unifilar.py,sha256=54Qaof-nzFlLbKiPTwFDstPySZoy34D8vjLtXx7k9GE,4486
42
+ sofic/automata/vpa.py,sha256=uBWlqF6qaRv4CJldnPXEUnC5vkP3GcnJ2OZir7BmqqE,58567
43
+ sofic/automata/vpa_simulation.py,sha256=YL3zRQUy4CLMvRWupBLur9ImjUJ7-0y24ha4ZDT-Zsg,2086
44
+ sofic/automata/languages/__init__.py,sha256=hVWvX4ZxePDo7gcThvbNRsL_nGqgxq7l8lUM8SoLKuw,994
45
+ sofic/automata/languages/_quotient_utils.py,sha256=NCIV29vwUP9kQBtqIj9TgNVPU7KHP8EBluxWNsPhVA0,2216
46
+ sofic/automata/languages/atoms.py,sha256=2fDfxlTikWLovDtffGysp0QQTrT8KzkfDesQne35sJk,1383
47
+ sofic/automata/languages/automaton_ops.py,sha256=v7hHPGW9Q9JTyGAFTRv9bi4DuxGobDFmQaTF_mZsXso,8703
48
+ sofic/automata/languages/base.py,sha256=CyBrTUgC3ATMd8JrxdkPvdG61w26K0Uka_JzkeHjFXQ,1997
49
+ sofic/automata/languages/operations.py,sha256=HZRrbgMmJzu8kF3cgLZK850nm0LEjLvAMqqFxZDOhjQ,3633
50
+ sofic/automata/languages/quotients.py,sha256=zeVsQPAQ07Mhhfy3Vhq_qrfc1EUVFTuixNzn_IFEo-Y,2892
51
+ sofic/automata/languages/residuals.py,sha256=JiB3cEsT6ZGg60xShc-hINrvkLjE93OxAXZC0Kos9bo,1046
52
+ sofic/examples/__init__.py,sha256=1GBuCJMFCbKDm9I-hR9vleR3vgOHiVDSTxNNjzzm4vo,2649
53
+ sofic/examples/epsilon_machines.py,sha256=ycpPrxyZy1_s18kAZfS25fMqidtwpzaRqV7Glsi56-o,40571
54
+ sofic/examples/processes.py,sha256=P2KcRN-5I1_EXFJQDqAU0Tl8ssSpxVV1eeHLVsHYye8,52439
55
+ sofic/examples/shifts.py,sha256=uKICqYSUAthqSL8snA_JUzouJfiFveTyNweZSDk4lnk,5415
56
+ sofic/generators/__init__.py,sha256=3XVm0LPR9F-0BWaEjA0YY2Ma3pgeFV91rBnw2sQx5uY,3884
57
+ sofic/generators/_word_measures.py,sha256=Xr4Coupl5do-OLz5OyKUggnD6zqjz74bJXrRpwnBl_A,2955
58
+ sofic/generators/alternative_complexity.py,sha256=Xd_5Cm6nj9nchGsnCS62E88iHJt5-tK4HWNOR3Ne6Ts,3489
59
+ sofic/generators/base.py,sha256=9XhX92SUOyEakHHcmbXtuv8AJ1ubbshuIDU0y4mR6NA,12895
60
+ sofic/generators/bidirectional_construction.py,sha256=PbFlPCR2MkO8_kc9NM3PSoWylc7dY32rYTWC6YcbwF8,27476
61
+ sofic/generators/bidirectional_epsilon_machine.py,sha256=-DHWbCWOoIabRagMC6RUZz8RoBFrj49HXaGQq_qJYIk,30966
62
+ sofic/generators/block_convergence.py,sha256=l3cVnob9a4rEmlmtrEKbR33Cmbi2mF47AwZgM-w7n6Y,25885
63
+ sofic/generators/block_entropy.py,sha256=IdypvElTpJWbieo95Z6n_cp2IqF9Og_Z9PFj6lIxlGA,21587
64
+ sofic/generators/channel_measures.py,sha256=eYYItbcei9rYwZZZTK5NkGe61pacC221nV37HHkyzzc,3386
65
+ sofic/generators/conversions.py,sha256=tpRUaJUXLz8g07QcGO4b5hxEqqzgW7UwwVh5WMaWzMw,6596
66
+ sofic/generators/directional_flow.py,sha256=WyHhLF_l2-p5-F6TT5JHlH4LurqnD_Ion2-FiRpA5Vk,8312
67
+ sofic/generators/edge_emissions.py,sha256=ydNUrclW24gcPmaqbGVAEy0atrr577VhJUi80P5NkMI,1521
68
+ sofic/generators/edge_machine.py,sha256=nnbIXOrruKGiyy4jZzVphjhPBh6rOTyhdx5-U6f8mTY,6222
69
+ sofic/generators/epsilon_construction.py,sha256=H-VQ06MoL2y0u5whKmSVy5jps-1KUrjKQnzXll1wpQA,6888
70
+ sofic/generators/epsilon_inference.py,sha256=3ky0Cw85H6uRLODPu-jCGCpUxrWLVpvX5hnlKdfLhKI,27141
71
+ sofic/generators/epsilon_machine.py,sha256=jBjc2x71MPaN0RzFSHv6AWF9HmGxkW6RYgN7wBXE7nw,25711
72
+ sofic/generators/epsilon_transducer.py,sha256=wNhatXuH7CW-5UAUa6rauCKJYvamr-MjAWWQlw8HGms,7320
73
+ sofic/generators/epsilon_transducer_construction.py,sha256=f_IwrsPPjVSy2XatGG72WzB0Dj1NduUlIh73yh9eFPc,7358
74
+ sofic/generators/epsilon_transducer_inference.py,sha256=gVusFjCOEwNgfohti7PoXQo0xhz8pinMbnN3gwbXma4,19747
75
+ sofic/generators/hmm_inference.py,sha256=FqjlcumjWMUuLY06osp6j3-227RszuAmYn4LKDXvI4c,29280
76
+ sofic/generators/information_diagram.py,sha256=PnBitp04_v6EevAitiFy2zzmMV-Z9MTBPRxiKcuIA3E,15319
77
+ sofic/generators/lumping.py,sha256=AqWeanqXDSpwJ7ZLErLc2zveMm_zVUXcv1PBE6i3TQY,16910
78
+ sofic/generators/markov.py,sha256=ToNzWnH_hJh-B3vxB-SZO8hDMgdunlX85hxF2j23GYI,4091
79
+ sofic/generators/mealy.py,sha256=_5GPCqM9J4vvwi4Bjq4RxQGn5Kcd6YZbw2oks3SyFNQ,5925
80
+ sofic/generators/measures.py,sha256=ai4gAlhqo2Q5_GOM4-LRlVpf-QmQ0--_qn0iGAHiLog,9612
81
+ sofic/generators/minimal_generative_model.py,sha256=7LaVRkvEdvjEbpVtKNe62Pxj_HD2nC17otre8OHobMA,31000
82
+ sofic/generators/mixed_state.py,sha256=qlzV7VygK5vwkd0Lt56868qkHV-NayBUOinhEEm23lI,9161
83
+ sofic/generators/mixed_state_construction.py,sha256=UJNqo8VF7-fNz5HzBHq9UnnUbVyXN0NaT60adybHOVo,6013
84
+ sofic/generators/moore.py,sha256=vyAVzDs8slz_sKl3OGTyAclc_XcOjUehm8v96yA_STk,3209
85
+ sofic/generators/nmachine.py,sha256=WqRuJrEztwEkA1V6i22hxqzYY8LS_whF2fGkUIq_OoQ,3167
86
+ sofic/generators/nmachine_construction.py,sha256=bhh5XXI1cyNYS-qstPngQ9xYLjwg5-lray0HELtDTR0,2548
87
+ sofic/generators/pfa.py,sha256=MA1owkSr_d0fBVLrrdXb7b3AMKUUBYy3KsFa2-za5MI,3972
88
+ sofic/generators/prob.py,sha256=UxqnQed4XvdmKueHKvX-kklmbrmNipLkP0tHNow3qSw,10614
89
+ sofic/generators/process_equivalence.py,sha256=UKORNNeK5Zis6TLJiIknz3NsPD8iL5CWoeeVxnILlfc,7612
90
+ sofic/generators/quasi_inference.py,sha256=a1UdSIpIRH4pTulqrwGCRc6Zt4TnrKll1D7NE5oQha4,2415
91
+ sofic/generators/quasi_realization.py,sha256=QQosziYqNHEPo1Su4Qjp9k0zBxpqi4wzxUwRahZ57Wk,3501
92
+ sofic/generators/reversal.py,sha256=EGf8KP507Ho1oATqdK1dePqZH4hN7eafJF8DHMJGtYY,2453
93
+ sofic/generators/stack_hmm.py,sha256=I_SBENucbWdnTQKKx-HP760X06xKOJylfQC-L70fYp8,18868
94
+ sofic/generators/stack_inference.py,sha256=wCFbP8kbB2Flzp61N8uN6wkcoCY_wE-mDBw-vFTM40I,18000
95
+ sofic/generators/stationary.py,sha256=nN0ugt61Bl1xiY-8ITF-T__0rfkK0icsbwhQapTLZxM,4992
96
+ sofic/generators/stochastic.py,sha256=_mSfLCxGG_NmA42tvV-kBOzWSgqH6n30uX_igITwVxU,2223
97
+ sofic/generators/synchronization.py,sha256=q8VHzMjLFHITpax5wHlG5a3gSfxOgXwNBW5cnng9q5I,16787
98
+ sofic/generators/topological_epsilon_enumeration.py,sha256=ohxAVtEruXzvDbcqB2AmcIvcDyYVz8xoyh2h2X1CoKQ,12572
99
+ sofic/generators/words.py,sha256=ZZMsAumG8_jMy90GcwLBw1-PkljOM2pfI7rGAy40jVA,8382
100
+ sofic/inference/__init__.py,sha256=9x1af3bORgxAKKs4RJRtsXCATsZsK3BmoJPvETCoYi0,1108
101
+ sofic/inference/model_selection.py,sha256=_s38_lYOmvY_t7TOLaOHArYKrdM3qgRyOU9UBzoC5S8,14099
102
+ sofic/inference/spectral.py,sha256=o6XGTaJkQUaV0SWA-5Xun02bHrvKsONo0dMZOXl6WKU,22108
103
+ sofic/inference/bayesian/__init__.py,sha256=xuf70Lejgo-2mdiyDH6MVwocXzMBYiaMUlbmQT9e0yE,2056
104
+ sofic/inference/bayesian/comparison.py,sha256=ZrQbKRS2jkpa7x9gJZp6aIoOv9CFUgeghklZN-LjzNo,7952
105
+ sofic/inference/bayesian/counts.py,sha256=vd-J_plBsr6oFZFfniqdfGSUdVGlucaw2PKb8JmDcvo,8105
106
+ sofic/inference/bayesian/diversity.py,sha256=xfjf8qx6c5cNSFEoutSIz1-JFOwA8ymyTzpe3NTOAZA,9929
107
+ sofic/inference/bayesian/epsilon.py,sha256=sOBoM5oXvqNJG714i30u4JmM472oywRPTCAlWVYaBAI,12035
108
+ sofic/inference/bayesian/hdp_hmm.py,sha256=hbMyknq7RgN-p2akqFc5aKuF2mhSIwy1Aqen-ytPbdY,13749
109
+ sofic/inference/bayesian/markov.py,sha256=_OsE3pZkFxbEGSJ_bDne3NWw5GSM8gBFhMQMitLni6o,12697
110
+ sofic/inference/bayesian/pymc_backend.py,sha256=YMq-2PkUWX3ZXXZSZPdIYfSOXHi2kaeM2mqfaABo6SA,2984
111
+ sofic/inference/bayesian/stack_hmm.py,sha256=wdtv1qOgRxRcdfwaO1OAXx_q2HJRGDqFGszyRVoSoVA,8566
112
+ sofic/shifts/__init__.py,sha256=8MAtvrdAghmtLFwQY0PA5d8jFUg4_5wGl19ESd5Yors,1373
113
+ sofic/shifts/algorithms.py,sha256=JxfvlSWvz9n2j10HCYcclyhk6CfvPc_oOaGkQWcWkHE,2769
114
+ sofic/shifts/base.py,sha256=IFlL_kMv6MTeQD3wMljmnw6G9xBB5Mz7U6rXdRWkHCg,1844
115
+ sofic/shifts/cover_construction.py,sha256=aiRNyhWds7eJ_VAyTzMJlMlNH9L3gf-A0ojba0r9RR0,2901
116
+ sofic/shifts/covers.py,sha256=x8qcbRQIrj6gH8oL9WJLBbeZulmecvsHx1i0daGRCGw,1367
117
+ sofic/shifts/dyck_algorithms.py,sha256=sTuqbjkD2cLydrEwd9i-pKuWOvmzzhwVw84Hsys6KVo,3479
118
+ sofic/shifts/dyck_enumeration.py,sha256=4eQXDu-3J2-J1Pg_qSvhCT9upnFWs9Bof3Qndl0Pthc,10165
119
+ sofic/shifts/markov_dyck.py,sha256=KA8sbHY59xDDVBVNkJUzb8xgBTbcENijlwQFujzcVvs,6813
120
+ sofic/shifts/parry_construction.py,sha256=JLwlXeqvO-bIro5RVXCo0xADsn4s_JhUx-VI2QTn9AI,2823
121
+ sofic/shifts/sft.py,sha256=RSB7zSDlpggdU47AdhtM6xOm02YJHIGZ38JhvKLsMKg,3973
122
+ sofic/shifts/sft_construction.py,sha256=V-PRlhInOOlU_nXQNU7vZLgGEDw-5VueP3K7RaSV5w0,1603
123
+ sofic/shifts/sliding_block_code.py,sha256=RaZXzSNcc1RZsQnglmY7BVhK6VI0HEpvvPuWqRefsyU,6602
124
+ sofic/shifts/sofic.py,sha256=Pghqv4ODoYbRdOhvgUIjaasCXu4vD89bY1cR-AlIBIM,4690
125
+ sofic/shifts/sofic_dyck.py,sha256=MRsImxWj4gAn32KDVAskygHUg3MJX13SmsEoflzEjG4,5569
126
+ sofic/shifts/sofic_relation.py,sha256=PCF30jOSCS5lsWOGOUd0MGCopg6fOBGbMDeV1Yj1ehc,2707
127
+ sofic/shifts/textile.py,sha256=JC8Y6Wjdj5KQdObPDtROdzFdydyRMAtoresaaE5n8PM,4632
128
+ sofic/shifts/tmc.py,sha256=kSwBRGiUyErW8oVBvjinItIFfdUZo-oluqhjzfYzHKo,1442
129
+ sofic/shifts/tmc_construction.py,sha256=bOB8UcaK81P1NfDPwqV3i_IpD2Bz0hDldmSbReYi0aM,2047
130
+ sofic/shifts/topological_anatomy.py,sha256=VzTNX_iih91UZmTDcc856IfquWKmNDnBfmgvIX1XAwg,6687
131
+ sofic/testing/__init__.py,sha256=iXB73G_LmxCYQpE0_QgR5pBkJoRSQBYrKEgKoUQLcZY,167
132
+ sofic/testing/strategies.py,sha256=6CW77uTRioBX9jpSnj-cL4Rep-tCt7zuLIc-WZWW5_A,5210
133
+ sofic/viz/__init__.py,sha256=cvH7NCrlgakhONsUZkQYhwaE0iaIdqdVnNStUWg7jk8,479
134
+ sofic/viz/_context.py,sha256=e8VGhiLyQa7O5WK9FZjrSozEqzl66N9V8oE90TMMVPs,12608
135
+ sofic/viz/_edge.py,sha256=B2TXmelVbqdQ_ulq2E9ZDvvftcisDDnWhLIqQC_J33c,7825
136
+ sofic/viz/_format.py,sha256=-JQSm_Z185OnIpU8hdViCfJnnk6O3dJvlv7NpPRNExo,2730
137
+ sofic/viz/_labels.py,sha256=C67PJVjVMufAUmgoKKc2wvtxfFMuK8BRXzQ82sg5VpE,1314
138
+ sofic/viz/_names.py,sha256=8IE3AbvOTCMU8IRdj-0dOV1LeOtWLPTO4AObcRo9t_0,447
139
+ sofic/viz/_rational.py,sha256=pZ0IAm0LD1WgpScyCy9a5m1sySw5ppSsiVg0wRid1j0,721
140
+ sofic/viz/_tikz_compile.py,sha256=5cVshbDklLtafvNh1lZyf2NccFhtqsmfmt2GxPDnC-E,5942
141
+ sofic/viz/_tikz_format.py,sha256=bYHQt2K22fFoduDm3u8VhD0YBApYi0oGCJKP8wtWQFM,3782
142
+ sofic/viz/_tikz_layout.py,sha256=BzmOYzsCCFRqVRbAwCwJUQq2lSLv0LD0270Qc-6A-As,7406
143
+ sofic/viz/graphviz.py,sha256=0I3JEsJ-dIjR8Wn0Oj0_YRdWPfn_p47lQgEigu9G1Wk,5174
144
+ sofic/viz/idiagram.py,sha256=w1QyptmuwmwXx9O_Xms3oWXdr1NL5naOdD8H5Lf2N5c,12796
145
+ sofic/viz/tikz.py,sha256=FSzRU3WFQDTpe5a4kMiau28xgYf83lAw_w0TTF_Inds,13445
146
+ sofic/viz/assets/vaucanson.tikz,sha256=Mrrrv8zOUfjSUzvAkFUsYVB4AdJH5ymLdO5C-QTsK0c,2657
147
+ sofic-0.1.0.dist-info/METADATA,sha256=Fi8DbQFbtrxMOyyulmyo7P3989MUqsI_cYC2r2-Fk4s,15613
148
+ sofic-0.1.0.dist-info/WHEEL,sha256=zOwg4jB6zX2kU910N-cMawjivD6tO8NEWvE12je1bVk,87
149
+ sofic-0.1.0.dist-info/licenses/LICENSE.txt,sha256=ezk-F-oQ6gQkTLC1BA1JLl26_Ou5W01ofFriVuRY5Qs,1519
150
+ sofic-0.1.0.dist-info/RECORD,,
@@ -0,0 +1,4 @@
1
+ Wheel-Version: 1.0
2
+ Generator: hatchling 1.32.0
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
@@ -0,0 +1,29 @@
1
+ BSD 3-Clause License
2
+
3
+ Copyright (c) 2026, sofic contributors.
4
+ All rights reserved.
5
+
6
+ Redistribution and use in source and binary forms, with or without
7
+ modification, are permitted provided that the following conditions are met:
8
+
9
+ * Redistributions of source code must retain the above copyright notice, this
10
+ list of conditions and the following disclaimer.
11
+
12
+ * Redistributions in binary form must reproduce the above copyright notice,
13
+ this list of conditions and the following disclaimer in the documentation
14
+ and/or other materials provided with the distribution.
15
+
16
+ * Neither the name of the copyright holder nor the names of its
17
+ contributors may be used to endorse or promote products derived from
18
+ this software without specific prior written permission.
19
+
20
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
23
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
24
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
26
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
27
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
28
+ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.