morphata 2.0.6__tar.gz → 2.0.7__tar.gz
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.
- {morphata-2.0.6 → morphata-2.0.7}/CHANGELOG.md +7 -0
- {morphata-2.0.6 → morphata-2.0.7}/PKG-INFO +1 -1
- {morphata-2.0.6 → morphata-2.0.7}/pyproject.toml +1 -1
- {morphata-2.0.6 → morphata-2.0.7}/src/morphata/symbolic/persistence.py +45 -10
- {morphata-2.0.6 → morphata-2.0.7}/tests/symbolic/test_persistence.py +50 -0
- {morphata-2.0.6 → morphata-2.0.7}/uv.lock +1 -1
- {morphata-2.0.6 → morphata-2.0.7}/.basedpyright/baseline.json +0 -0
- {morphata-2.0.6 → morphata-2.0.7}/.claude/settings.local.json +0 -0
- {morphata-2.0.6 → morphata-2.0.7}/.dockerignore +0 -0
- {morphata-2.0.6 → morphata-2.0.7}/.editorconfig +0 -0
- {morphata-2.0.6 → morphata-2.0.7}/.envrc +0 -0
- {morphata-2.0.6 → morphata-2.0.7}/.envrc.recommended +0 -0
- {morphata-2.0.6 → morphata-2.0.7}/.fdignore +0 -0
- {morphata-2.0.6 → morphata-2.0.7}/.gitattributes +0 -0
- {morphata-2.0.6 → morphata-2.0.7}/.gitignore +0 -0
- {morphata-2.0.6 → morphata-2.0.7}/.mailmap +0 -0
- {morphata-2.0.6 → morphata-2.0.7}/.python-version +0 -0
- {morphata-2.0.6 → morphata-2.0.7}/.rstcheck.cfg +0 -0
- {morphata-2.0.6 → morphata-2.0.7}/AGENTS.md +0 -0
- {morphata-2.0.6 → morphata-2.0.7}/CLAUDE.md +0 -0
- {morphata-2.0.6 → morphata-2.0.7}/CONTRIBUTING.md +0 -0
- {morphata-2.0.6 → morphata-2.0.7}/LICENSE +0 -0
- {morphata-2.0.6 → morphata-2.0.7}/README.md +0 -0
- {morphata-2.0.6 → morphata-2.0.7}/bench/README.md +0 -0
- {morphata-2.0.6 → morphata-2.0.7}/bench/__init__.py +0 -0
- {morphata-2.0.6 → morphata-2.0.7}/bench/conftest.py +0 -0
- {morphata-2.0.6 → morphata-2.0.7}/bench/test_sere_nlm_perf.py +0 -0
- {morphata-2.0.6 → morphata-2.0.7}/ci/make-release +0 -0
- {morphata-2.0.6 → morphata-2.0.7}/cliff.toml +0 -0
- {morphata-2.0.6 → morphata-2.0.7}/docs/_static/navigation.html +0 -0
- {morphata-2.0.6 → morphata-2.0.7}/docs/api/modules.rst +0 -0
- {morphata-2.0.6 → morphata-2.0.7}/docs/api/morphata.acceptance.rst +0 -0
- {morphata-2.0.6 → morphata-2.0.7}/docs/api/morphata.alphabet.rst +0 -0
- {morphata-2.0.6 → morphata-2.0.7}/docs/api/morphata.automaton.rst +0 -0
- {morphata-2.0.6 → morphata-2.0.7}/docs/api/morphata.builder.rst +0 -0
- {morphata-2.0.6 → morphata-2.0.7}/docs/api/morphata.hoa.rst +0 -0
- {morphata-2.0.6 → morphata-2.0.7}/docs/api/morphata.logic.ltl.rst +0 -0
- {morphata-2.0.6 → morphata-2.0.7}/docs/api/morphata.logic.psl.rst +0 -0
- {morphata-2.0.6 → morphata-2.0.7}/docs/api/morphata.logic.sere.rst +0 -0
- {morphata-2.0.6 → morphata-2.0.7}/docs/api/morphata.logic.strel.rst +0 -0
- {morphata-2.0.6 → morphata-2.0.7}/docs/api/morphata.operators.matrix.rst +0 -0
- {morphata-2.0.6 → morphata-2.0.7}/docs/api/morphata.operators.polynomial.rst +0 -0
- {morphata-2.0.6 → morphata-2.0.7}/docs/api/morphata.operators.rst +0 -0
- {morphata-2.0.6 → morphata-2.0.7}/docs/api/morphata.symbolic.rst +0 -0
- {morphata-2.0.6 → morphata-2.0.7}/docs/concepts/acceptance.rst +0 -0
- {morphata-2.0.6 → morphata-2.0.7}/docs/concepts/hoa.rst +0 -0
- {morphata-2.0.6 → morphata-2.0.7}/docs/concepts/index.rst +0 -0
- {morphata-2.0.6 → morphata-2.0.7}/docs/concepts/operators.rst +0 -0
- {morphata-2.0.6 → morphata-2.0.7}/docs/concepts/spec.rst +0 -0
- {morphata-2.0.6 → morphata-2.0.7}/docs/concepts/weights.rst +0 -0
- {morphata-2.0.6 → morphata-2.0.7}/docs/conf.py +0 -0
- {morphata-2.0.6 → morphata-2.0.7}/docs/index.rst +0 -0
- {morphata-2.0.6 → morphata-2.0.7}/docs/quick-start.rst +0 -0
- {morphata-2.0.6 → morphata-2.0.7}/docs/symbolic-transforms.rst +0 -0
- {morphata-2.0.6 → morphata-2.0.7}/justfile +0 -0
- {morphata-2.0.6 → morphata-2.0.7}/mypy.ini +0 -0
- {morphata-2.0.6 → morphata-2.0.7}/pixi.lock +0 -0
- {morphata-2.0.6 → morphata-2.0.7}/pixi.toml +0 -0
- {morphata-2.0.6 → morphata-2.0.7}/project.utf-8.add +0 -0
- {morphata-2.0.6 → morphata-2.0.7}/project.utf-8.add.spl +0 -0
- {morphata-2.0.6 → morphata-2.0.7}/pyrefly.toml +0 -0
- {morphata-2.0.6 → morphata-2.0.7}/pyrightconfig.json +0 -0
- {morphata-2.0.6 → morphata-2.0.7}/pytest.toml +0 -0
- {morphata-2.0.6 → morphata-2.0.7}/ruff.toml +0 -0
- {morphata-2.0.6 → morphata-2.0.7}/src/morphata/__init__.py +0 -0
- {morphata-2.0.6 → morphata-2.0.7}/src/morphata/acceptance.py +0 -0
- {morphata-2.0.6 → morphata-2.0.7}/src/morphata/alphabet.py +0 -0
- {morphata-2.0.6 → morphata-2.0.7}/src/morphata/automaton.py +0 -0
- {morphata-2.0.6 → morphata-2.0.7}/src/morphata/builder.py +0 -0
- {morphata-2.0.6 → morphata-2.0.7}/src/morphata/hoa/__init__.py +0 -0
- {morphata-2.0.6 → morphata-2.0.7}/src/morphata/hoa/__main__.py +0 -0
- {morphata-2.0.6 → morphata-2.0.7}/src/morphata/hoa/acc_expr.py +0 -0
- {morphata-2.0.6 → morphata-2.0.7}/src/morphata/hoa/exporter.py +0 -0
- {morphata-2.0.6 → morphata-2.0.7}/src/morphata/hoa/hoa.lark +0 -0
- {morphata-2.0.6 → morphata-2.0.7}/src/morphata/hoa/parser.py +0 -0
- {morphata-2.0.6 → morphata-2.0.7}/src/morphata/logic/__init__.py +0 -0
- {morphata-2.0.6 → morphata-2.0.7}/src/morphata/logic/_common.py +0 -0
- {morphata-2.0.6 → morphata-2.0.7}/src/morphata/logic/ltl.py +0 -0
- {morphata-2.0.6 → morphata-2.0.7}/src/morphata/logic/psl.py +0 -0
- {morphata-2.0.6 → morphata-2.0.7}/src/morphata/logic/sere.py +0 -0
- {morphata-2.0.6 → morphata-2.0.7}/src/morphata/logic/strel.py +0 -0
- {morphata-2.0.6 → morphata-2.0.7}/src/morphata/operators/__init__.py +0 -0
- {morphata-2.0.6 → morphata-2.0.7}/src/morphata/operators/_backend.py +0 -0
- {morphata-2.0.6 → morphata-2.0.7}/src/morphata/operators/matrix.py +0 -0
- {morphata-2.0.6 → morphata-2.0.7}/src/morphata/operators/polynomial.py +0 -0
- {morphata-2.0.6 → morphata-2.0.7}/src/morphata/py.typed +0 -0
- {morphata-2.0.6 → morphata-2.0.7}/src/morphata/symbolic/__init__.py +0 -0
- {morphata-2.0.6 → morphata-2.0.7}/src/morphata/symbolic/automaton.py +0 -0
- {morphata-2.0.6 → morphata-2.0.7}/src/morphata/symbolic/bdd.py +0 -0
- {morphata-2.0.6 → morphata-2.0.7}/src/morphata/symbolic/compose.py +0 -0
- {morphata-2.0.6 → morphata-2.0.7}/src/morphata/symbolic/equivalence.py +0 -0
- {morphata-2.0.6 → morphata-2.0.7}/src/morphata/symbolic/transforms.py +0 -0
- {morphata-2.0.6 → morphata-2.0.7}/tests/conftest.py +0 -0
- {morphata-2.0.6 → morphata-2.0.7}/tests/hoa/aut1.hoa +0 -0
- {morphata-2.0.6 → morphata-2.0.7}/tests/hoa/aut11.hoa +0 -0
- {morphata-2.0.6 → morphata-2.0.7}/tests/hoa/aut2.hoa +0 -0
- {morphata-2.0.6 → morphata-2.0.7}/tests/hoa/aut3.2.hoa +0 -0
- {morphata-2.0.6 → morphata-2.0.7}/tests/hoa/aut3.hoa +0 -0
- {morphata-2.0.6 → morphata-2.0.7}/tests/hoa/aut4.hoa +0 -0
- {morphata-2.0.6 → morphata-2.0.7}/tests/hoa/aut5.hoa +0 -0
- {morphata-2.0.6 → morphata-2.0.7}/tests/hoa/aut6.hoa +0 -0
- {morphata-2.0.6 → morphata-2.0.7}/tests/hoa/aut7.hoa +0 -0
- {morphata-2.0.6 → morphata-2.0.7}/tests/hoa/aut8.hoa +0 -0
- {morphata-2.0.6 → morphata-2.0.7}/tests/hoa/finite_aut.hoa +0 -0
- {morphata-2.0.6 → morphata-2.0.7}/tests/hoa/gen_buchi_3.hoa +0 -0
- {morphata-2.0.6 → morphata-2.0.7}/tests/hoa/gen_cobuchi_2.hoa +0 -0
- {morphata-2.0.6 → morphata-2.0.7}/tests/hoa/rabin_2pair.hoa +0 -0
- {morphata-2.0.6 → morphata-2.0.7}/tests/hoa/streett_2pair.hoa +0 -0
- {morphata-2.0.6 → morphata-2.0.7}/tests/hoa/test_exporter_basic.py +0 -0
- {morphata-2.0.6 → morphata-2.0.7}/tests/hoa/test_exporter_roundtrip.py +0 -0
- {morphata-2.0.6 → morphata-2.0.7}/tests/hoa/test_exporter_streaming.py +0 -0
- {morphata-2.0.6 → morphata-2.0.7}/tests/hoa/test_parser.py +0 -0
- {morphata-2.0.6 → morphata-2.0.7}/tests/logic/__init__.py +0 -0
- {morphata-2.0.6 → morphata-2.0.7}/tests/logic/test_ltl.py +0 -0
- {morphata-2.0.6 → morphata-2.0.7}/tests/logic/test_psl.py +0 -0
- {morphata-2.0.6 → morphata-2.0.7}/tests/logic/test_sere.py +0 -0
- {morphata-2.0.6 → morphata-2.0.7}/tests/logic/test_sere_properties.py +0 -0
- {morphata-2.0.6 → morphata-2.0.7}/tests/logic/test_strel.py +0 -0
- {morphata-2.0.6 → morphata-2.0.7}/tests/operators/test_matrix_from_ir.py +0 -0
- {morphata-2.0.6 → morphata-2.0.7}/tests/operators/test_matrix_from_ltl.py +0 -0
- {morphata-2.0.6 → morphata-2.0.7}/tests/operators/test_polynomial_from_ir.py +0 -0
- {morphata-2.0.6 → morphata-2.0.7}/tests/symbolic/test_alphabet_aware_transitions.py +0 -0
- {morphata-2.0.6 → morphata-2.0.7}/tests/symbolic/test_bdd_helpers.py +0 -0
- {morphata-2.0.6 → morphata-2.0.7}/tests/symbolic/test_compose.py +0 -0
- {morphata-2.0.6 → morphata-2.0.7}/tests/symbolic/test_from_hoaf.py +0 -0
- {morphata-2.0.6 → morphata-2.0.7}/tests/symbolic/test_ltlf2dfa_equivalence.py +0 -0
- {morphata-2.0.6 → morphata-2.0.7}/tests/symbolic/test_step.py +0 -0
- {morphata-2.0.6 → morphata-2.0.7}/tests/symbolic/test_symbolic_automaton.py +0 -0
- {morphata-2.0.6 → morphata-2.0.7}/tests/symbolic/test_symbolic_from_ir.py +0 -0
- {morphata-2.0.6 → morphata-2.0.7}/tests/symbolic/test_to_hoa.py +0 -0
- {morphata-2.0.6 → morphata-2.0.7}/tests/symbolic/test_transforms.py +0 -0
- {morphata-2.0.6 → morphata-2.0.7}/tests/symbolic/test_transforms_ir.py +0 -0
- {morphata-2.0.6 → morphata-2.0.7}/tests/symbolic/test_transforms_properties.py +0 -0
- {morphata-2.0.6 → morphata-2.0.7}/tests/test_alphabet.py +0 -0
- {morphata-2.0.6 → morphata-2.0.7}/tests/test_automaton.py +0 -0
- {morphata-2.0.6 → morphata-2.0.7}/tests/test_builder.py +0 -0
- {morphata-2.0.6 → morphata-2.0.7}/tests/test_from_parsed.py +0 -0
- {morphata-2.0.6 → morphata-2.0.7}/ty.toml +0 -0
|
@@ -1,5 +1,12 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 2.0.7 — 2026-06-02
|
|
4
|
+
|
|
5
|
+
### Fixed
|
|
6
|
+
|
|
7
|
+
- The BDD JSON exporter in `dd.cudd` needed to be worked around because of a bug where
|
|
8
|
+
`mgr.true` and `mrg.false` do not survive a round trip serialization.
|
|
9
|
+
|
|
3
10
|
## 2.0.6 — 2026-06-02
|
|
4
11
|
|
|
5
12
|
### Fixed
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
name = "morphata"
|
|
3
3
|
authors = [{ name = "Anand Balakrishnan", email = "anandbala1597@gmail.com" }]
|
|
4
4
|
description = "Representation theory for automata, made practical."
|
|
5
|
-
version = "2.0.
|
|
5
|
+
version = "2.0.7"
|
|
6
6
|
requires-python = ">=3.12"
|
|
7
7
|
classifiers = [
|
|
8
8
|
"Intended Audience :: Science/Research",
|
|
@@ -189,6 +189,23 @@ def to_bdd_json(sym: "SymbolicAutomaton[Any]", path: str | Path) -> None:
|
|
|
189
189
|
rows_for_s.append([g_name, s_name])
|
|
190
190
|
transitions_layout[str(s)] = rows_for_s
|
|
191
191
|
|
|
192
|
+
# dd's JSON dump/load round-trip is buggy for terminal roots on the
|
|
193
|
+
# CUDD backend: ``_dump_bdd_info`` emits a numeric id for True/False
|
|
194
|
+
# roots while ``_dump_bdd`` short-circuits terminals as ``"T"`` /
|
|
195
|
+
# ``"F"`` and never writes a body for those ids, so ``manager.load``
|
|
196
|
+
# raises KeyError. Sidestep by filtering terminal roots out of the
|
|
197
|
+
# dict handed to dd.dump and recording their names in the sidecar.
|
|
198
|
+
true_root_names: list[str] = []
|
|
199
|
+
false_root_names: list[str] = []
|
|
200
|
+
bdd_roots: dict[str, Function] = {}
|
|
201
|
+
for name, node in roots.items():
|
|
202
|
+
if node == mgr.true:
|
|
203
|
+
true_root_names.append(name)
|
|
204
|
+
elif node == mgr.false:
|
|
205
|
+
false_root_names.append(name)
|
|
206
|
+
else:
|
|
207
|
+
bdd_roots[name] = node
|
|
208
|
+
|
|
192
209
|
ap_registry_json: dict[str, str] = {}
|
|
193
210
|
for ap, var in sym.ap_registry.items():
|
|
194
211
|
if not isinstance(ap, str):
|
|
@@ -207,13 +224,22 @@ def to_bdd_json(sym: "SymbolicAutomaton[Any]", path: str | Path) -> None:
|
|
|
207
224
|
"ap_var_format": AP_VAR_FORMAT,
|
|
208
225
|
"initial_root_name": "initial",
|
|
209
226
|
"transitions": transitions_layout,
|
|
227
|
+
"true_root_names": sorted(true_root_names),
|
|
228
|
+
"false_root_names": sorted(false_root_names),
|
|
229
|
+
# dd's dump raises if roots={}, so flag the all-terminal case and
|
|
230
|
+
# skip the BDD file altogether; the sidecar carries everything.
|
|
231
|
+
"bdd_file_empty": not bdd_roots,
|
|
210
232
|
}
|
|
211
233
|
|
|
212
|
-
|
|
234
|
+
if bdd_roots:
|
|
235
|
+
mgr.dump(str(bdd_partial), roots=bdd_roots, filetype="json")
|
|
213
236
|
with open(meta_partial, "w") as f:
|
|
214
237
|
json.dump(meta, f, indent=2, sort_keys=True)
|
|
215
238
|
|
|
216
|
-
|
|
239
|
+
if bdd_roots:
|
|
240
|
+
bdd_partial.replace(bdd_path)
|
|
241
|
+
elif bdd_path.exists():
|
|
242
|
+
bdd_path.unlink()
|
|
217
243
|
meta_partial.replace(meta_path)
|
|
218
244
|
|
|
219
245
|
|
|
@@ -267,14 +293,23 @@ def from_bdd_json(
|
|
|
267
293
|
if to_add:
|
|
268
294
|
manager.declare(*to_add)
|
|
269
295
|
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
296
|
+
if meta.get("bdd_file_empty", False):
|
|
297
|
+
roots: dict[str, Function] = {}
|
|
298
|
+
else:
|
|
299
|
+
loaded = manager.load(str(bdd_path))
|
|
300
|
+
if not isinstance(loaded, dict):
|
|
301
|
+
raise ValueError(
|
|
302
|
+
f"BDD JSON load returned {type(loaded).__name__}; expected a "
|
|
303
|
+
"dict of named roots. The file may have been written by a "
|
|
304
|
+
"different tool."
|
|
305
|
+
)
|
|
306
|
+
roots = loaded
|
|
307
|
+
|
|
308
|
+
# Restore terminal roots that were filtered out at dump time.
|
|
309
|
+
for name in meta.get("true_root_names", []):
|
|
310
|
+
roots[name] = manager.true
|
|
311
|
+
for name in meta.get("false_root_names", []):
|
|
312
|
+
roots[name] = manager.false
|
|
278
313
|
|
|
279
314
|
initial_name = meta["initial_root_name"]
|
|
280
315
|
try:
|
|
@@ -112,6 +112,56 @@ class TestAcceptanceRoundTrip:
|
|
|
112
112
|
assert _acceptance_from_json(_acceptance_to_json(cond)) == cond
|
|
113
113
|
|
|
114
114
|
|
|
115
|
+
class TestTerminalRoots:
|
|
116
|
+
"""Regression tests for the dd CUDD-backend terminal-root dump bug.
|
|
117
|
+
|
|
118
|
+
Why: ``mgr.dump(..., filetype='json')`` emits a numeric node id for
|
|
119
|
+
True/False roots without a body, and ``mgr.load`` then KeyError's
|
|
120
|
+
when looking up that id. ``to_bdd_json`` works around it by lifting
|
|
121
|
+
terminal roots into the sidecar.
|
|
122
|
+
"""
|
|
123
|
+
|
|
124
|
+
def test_a_u_b_round_trip(self, tmp_path: Path) -> None:
|
|
125
|
+
# Min-DFA for `a U b` has a True-guarded accepting sink; the
|
|
126
|
+
# row pointing at it produces a terminal-True succ root.
|
|
127
|
+
a = logic.Variable("a")
|
|
128
|
+
b = logic.Variable("b")
|
|
129
|
+
builder = AutomatonBuilder[int, str]()
|
|
130
|
+
builder.add_state(0, initial=True)
|
|
131
|
+
builder.add_state(1, accepting=True)
|
|
132
|
+
builder.add_state(2)
|
|
133
|
+
builder.add_transition(0, b, 1)
|
|
134
|
+
builder.add_transition(0, logic.And((a, logic.Not(b))), 0)
|
|
135
|
+
builder.add_transition(0, logic.And((logic.Not(a), logic.Not(b))), 2)
|
|
136
|
+
builder.add_transition(1, logic.Literal(True), 1)
|
|
137
|
+
builder.add_transition(2, logic.Literal(True), 2)
|
|
138
|
+
aut = builder.build()
|
|
139
|
+
sym = SymbolicAutomaton.from_automaton(aut, alphabet=powerset_alphabet(aut.predicates))
|
|
140
|
+
|
|
141
|
+
cache = tmp_path / "aub.bdd.json"
|
|
142
|
+
sym.to_bdd_json(cache)
|
|
143
|
+
loaded = SymbolicAutomaton.from_bdd_json(cache, alphabet=powerset_alphabet(frozenset(sym.ap_registry)))
|
|
144
|
+
assert loaded.num_states == sym.num_states
|
|
145
|
+
assert loaded.accepting_states == sym.accepting_states
|
|
146
|
+
assert language_equivalent(sym, loaded)
|
|
147
|
+
|
|
148
|
+
def test_all_terminal_roots(self, tmp_path: Path) -> None:
|
|
149
|
+
# 1-state automaton, only edge is a True-guarded self-loop.
|
|
150
|
+
# Every root (initial + guard + succ) is terminal.
|
|
151
|
+
builder = AutomatonBuilder[int, str]()
|
|
152
|
+
builder.add_state(0, initial=True, accepting=True)
|
|
153
|
+
builder.add_transition(0, logic.Literal(True), 0)
|
|
154
|
+
aut = builder.build()
|
|
155
|
+
sym = SymbolicAutomaton.from_automaton(aut, alphabet=powerset_alphabet(aut.predicates))
|
|
156
|
+
|
|
157
|
+
cache = tmp_path / "one.bdd.json"
|
|
158
|
+
sym.to_bdd_json(cache)
|
|
159
|
+
loaded = SymbolicAutomaton.from_bdd_json(cache, alphabet=powerset_alphabet(frozenset(sym.ap_registry)))
|
|
160
|
+
assert loaded.num_states == 1
|
|
161
|
+
assert loaded.accepting_states == frozenset({0})
|
|
162
|
+
assert language_equivalent(sym, loaded)
|
|
163
|
+
|
|
164
|
+
|
|
115
165
|
class TestSchemaGuard:
|
|
116
166
|
def test_mismatched_schema_version_raises(self, tmp_path: Path) -> None:
|
|
117
167
|
sym = _two_state_dfa()
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|