fable-engine 1.3.1__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.
- fable_compressor.py +356 -0
- fable_engine/__init__.py +1 -0
- fable_engine/actions/__init__.py +291 -0
- fable_engine/actions/cas.py +182 -0
- fable_engine/actions/deliberation.py +523 -0
- fable_engine/actions/fleet.py +807 -0
- fable_engine/actions/lifecycle.py +298 -0
- fable_engine/actions/scrapers.py +116 -0
- fable_engine/actions/system3.py +815 -0
- fable_engine/browser.py +824 -0
- fable_engine/cas.py +974 -0
- fable_engine/fable_session.json +510 -0
- fable_engine/guards.py +283 -0
- fable_engine/schema.py +714 -0
- fable_engine/scrapers/__init__.py +32 -0
- fable_engine/scrapers/arxiv.py +115 -0
- fable_engine/scrapers/base.py +386 -0
- fable_engine/scrapers/github.py +129 -0
- fable_engine/scrapers/reddit.py +154 -0
- fable_engine/scrapers/web.py +120 -0
- fable_engine/scrapers/x.py +125 -0
- fable_engine/scrapers/youtube.py +132 -0
- fable_engine/server.py +414 -0
- fable_engine/session.py +1819 -0
- fable_engine/test_server.py +1362 -0
- fable_engine/updater.py +541 -0
- fable_engine-1.3.1.dist-info/LICENSE +22 -0
- fable_engine-1.3.1.dist-info/METADATA +173 -0
- fable_engine-1.3.1.dist-info/RECORD +104 -0
- fable_engine-1.3.1.dist-info/WHEEL +5 -0
- fable_engine-1.3.1.dist-info/entry_points.txt +5 -0
- fable_engine-1.3.1.dist-info/top_level.txt +6 -0
- fable_mode/__init__.py +3 -0
- fable_mode/__main__.py +4 -0
- fable_mode/adapters.py +1014 -0
- fable_mode/installer.py +553 -0
- fable_mode/launcher.py +437 -0
- fable_mode/manifest.py +142 -0
- fable_mode/resources.json +114 -0
- fable_mode/safety.py +103 -0
- fable_mode_entry.py +10 -0
- fable_v2/__init__.py +146 -0
- fable_v2/adapters.py +151 -0
- fable_v2/coder_fleet/__init__.py +100 -0
- fable_v2/coder_fleet/ast_tools.py +158 -0
- fable_v2/coder_fleet/compute.py +199 -0
- fable_v2/coder_fleet/design_engine.py +1316 -0
- fable_v2/coder_fleet/diagnostics.py +293 -0
- fable_v2/coder_fleet/fleet_dispatcher.py +214 -0
- fable_v2/coder_fleet/mock_auditor.py +306 -0
- fable_v2/coder_fleet/mutation.py +216 -0
- fable_v2/coder_fleet/property_oracle.py +260 -0
- fable_v2/coder_fleet/receipt_attestor.py +122 -0
- fable_v2/coder_fleet/red_team_swarm.py +908 -0
- fable_v2/coder_fleet/test_harness.py +198 -0
- fable_v2/coder_fleet/vector_engine.py +1287 -0
- fable_v2/coder_fleet/visual.py +357 -0
- fable_v2/coder_fleet/workspace.py +153 -0
- fable_v2/cortical/__init__.py +20 -0
- fable_v2/cortical/plasticity_engine.py +992 -0
- fable_v2/execution_broker.py +811 -0
- fable_v2/proof_engine.py +1141 -0
- fable_v2/protocol.py +485 -0
- fable_v2/runtime.py +1010 -0
- fable_v2/system3/__init__.py +204 -0
- fable_v2/system3/causal.py +558 -0
- fable_v2/system3/dialectical.py +577 -0
- fable_v2/system3/evolution.py +503 -0
- fable_v2/system3/executive.py +338 -0
- fable_v2/system3/free_energy.py +479 -0
- fable_v2/system3/hyperbolic.py +555 -0
- fable_v2/system3/induction.py +336 -0
- fable_v2/system3/kripke.py +548 -0
- fable_v2/system3/oracle.py +745 -0
- fable_v2/verifiers.py +72 -0
- tests/__init__.py +1 -0
- tests/test_anti_loop_circuit_breaker.py +64 -0
- tests/test_auto_updater.py +407 -0
- tests/test_coder_fleet.py +535 -0
- tests/test_delegation_compiler.py +54 -0
- tests/test_descriptor_boundaries.py +126 -0
- tests/test_design_engine.py +603 -0
- tests/test_epistemic_evidence_validator.py +66 -0
- tests/test_execution_broker.py +233 -0
- tests/test_fable_v2.py +406 -0
- tests/test_fleet_transitions.py +116 -0
- tests/test_fsm_redteam_evolution.py +406 -0
- tests/test_goal_rubric_and_pipeline.py +367 -0
- tests/test_hebbian_plasticity.py +585 -0
- tests/test_packaging_runtime.py +194 -0
- tests/test_proof_engine.py +259 -0
- tests/test_red_team_swarm.py +645 -0
- tests/test_redteam_remediation.py +169 -0
- tests/test_registration_transaction.py +375 -0
- tests/test_requested_regressions.py +467 -0
- tests/test_scrapers.py +370 -0
- tests/test_server_actions.py +93 -0
- tests/test_server_frontier_actions.py +269 -0
- tests/test_server_protocol.py +88 -0
- tests/test_stealth_browser.py +970 -0
- tests/test_system3.py +381 -0
- tests/test_system3_deep_integration.py +385 -0
- tests/test_system3_frontier.py +436 -0
- tests/test_vector_engine.py +608 -0
|
@@ -0,0 +1,436 @@
|
|
|
1
|
+
"""Comprehensive Unit & Verification Test Suite for Frontier System 3 Transcendence Engine.
|
|
2
|
+
|
|
3
|
+
Tests:
|
|
4
|
+
1. Poincaré Hyperbolic Manifold (Metric tensor, Möbius addition, Exp/Log maps, Tree embeddings, Distortion)
|
|
5
|
+
2. Kripke Modal Model Checker (CTL* temporal operators: AG, EF, AF, AX, EX, EG, EU, AU; Box/Diamond; Witness & Counterexample traces)
|
|
6
|
+
3. Friston Active Inference Engine (Variational Free Energy F = Complexity - Accuracy, Expected Free Energy G, Policy Selection)
|
|
7
|
+
4. Gödelian Proof Oracle (Curry-Howard Isomorphism, Constructive Type Checking, Tactic Synthesis, Incompleteness / Paradox boundaries)
|
|
8
|
+
"""
|
|
9
|
+
|
|
10
|
+
from __future__ import annotations
|
|
11
|
+
|
|
12
|
+
import unittest
|
|
13
|
+
import math
|
|
14
|
+
import json
|
|
15
|
+
|
|
16
|
+
from fable_v2.system3 import (
|
|
17
|
+
# Hyperbolic
|
|
18
|
+
PoincareBall,
|
|
19
|
+
HyperbolicPoint,
|
|
20
|
+
HyperbolicTreeEmbedder,
|
|
21
|
+
TreeEmbeddingNode,
|
|
22
|
+
TreeEmbeddingResult,
|
|
23
|
+
HyperbolicGeometryError,
|
|
24
|
+
# Kripke
|
|
25
|
+
KripkeStructure,
|
|
26
|
+
KripkeWorld,
|
|
27
|
+
KripkeModelChecker,
|
|
28
|
+
ModelCheckResult,
|
|
29
|
+
CTLOperator,
|
|
30
|
+
FormulaNode,
|
|
31
|
+
FormulaParser,
|
|
32
|
+
# Free Energy
|
|
33
|
+
ActiveInferenceEngine,
|
|
34
|
+
GenerativeModel,
|
|
35
|
+
Policy,
|
|
36
|
+
PolicyEvaluation,
|
|
37
|
+
FreeEnergyReport,
|
|
38
|
+
create_default_architecture_pomdp,
|
|
39
|
+
# Oracle
|
|
40
|
+
ProofOracle,
|
|
41
|
+
CurryHowardVerifier,
|
|
42
|
+
UndecidabilityDetector,
|
|
43
|
+
TacticsEngine,
|
|
44
|
+
FormalProofResult,
|
|
45
|
+
ProofStatus,
|
|
46
|
+
Type,
|
|
47
|
+
Term,
|
|
48
|
+
Prop,
|
|
49
|
+
Unit,
|
|
50
|
+
Void,
|
|
51
|
+
Implies,
|
|
52
|
+
And,
|
|
53
|
+
Or,
|
|
54
|
+
Not,
|
|
55
|
+
Eq,
|
|
56
|
+
Var,
|
|
57
|
+
Lam,
|
|
58
|
+
App,
|
|
59
|
+
Pair,
|
|
60
|
+
Fst,
|
|
61
|
+
Snd,
|
|
62
|
+
Inl,
|
|
63
|
+
Inr,
|
|
64
|
+
Case,
|
|
65
|
+
Refl,
|
|
66
|
+
Abort,
|
|
67
|
+
)
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
class TestPoincareHyperbolicManifold(unittest.TestCase):
|
|
71
|
+
"""Unit tests for Poincaré Ball hyperbolic geometry and tree embeddings."""
|
|
72
|
+
|
|
73
|
+
def setUp(self):
|
|
74
|
+
self.manifold = PoincareBall(dimension=2, curvature=1.0)
|
|
75
|
+
|
|
76
|
+
def test_point_creation_and_clamping(self):
|
|
77
|
+
p1 = HyperbolicPoint(coords=(0.2, 0.3), curvature=1.0)
|
|
78
|
+
self.assertEqual(p1.dimension, 2)
|
|
79
|
+
self.assertAlmostEqual(p1.norm, math.sqrt(0.04 + 0.09), places=5)
|
|
80
|
+
|
|
81
|
+
# Out-of-bounds point should be automatically clamped inside unit disk
|
|
82
|
+
p_out = HyperbolicPoint(coords=(1.5, 0.0), curvature=1.0)
|
|
83
|
+
self.assertLess(p_out.norm, 1.0)
|
|
84
|
+
|
|
85
|
+
# Invalid curvature should raise
|
|
86
|
+
with self.assertRaises(ValueError):
|
|
87
|
+
HyperbolicPoint(coords=(0.1, 0.1), curvature=-1.0)
|
|
88
|
+
|
|
89
|
+
def test_conformal_factor_and_metric_tensor(self):
|
|
90
|
+
origin = (0.0, 0.0)
|
|
91
|
+
lam_0 = self.manifold.conformal_factor(origin)
|
|
92
|
+
self.assertAlmostEqual(lam_0, 2.0, places=5)
|
|
93
|
+
|
|
94
|
+
tensor_0 = self.manifold.metric_tensor(origin)
|
|
95
|
+
self.assertEqual(tensor_0, [[4.0, 0.0], [0.0, 4.0]])
|
|
96
|
+
|
|
97
|
+
# Near boundary, conformal factor grows to infinity
|
|
98
|
+
p_near = (0.9, 0.0)
|
|
99
|
+
lam_near = self.manifold.conformal_factor(p_near)
|
|
100
|
+
self.assertAlmostEqual(lam_near, 2.0 / (1.0 - 0.81), places=4)
|
|
101
|
+
self.assertGreater(lam_near, 10.0)
|
|
102
|
+
|
|
103
|
+
def test_mobius_addition_algebra(self):
|
|
104
|
+
x = (0.3, 0.2)
|
|
105
|
+
y = (-0.1, 0.4)
|
|
106
|
+
zero = (0.0, 0.0)
|
|
107
|
+
|
|
108
|
+
# Identity: x (+) 0 = x
|
|
109
|
+
x_plus_zero = self.manifold.mobius_add(x, zero)
|
|
110
|
+
self.assertAlmostEqual(x_plus_zero[0], x[0], places=5)
|
|
111
|
+
self.assertAlmostEqual(x_plus_zero[1], x[1], places=5)
|
|
112
|
+
|
|
113
|
+
# Inverse: x (+) (-x) = 0
|
|
114
|
+
neg_x = (-x[0], -x[1])
|
|
115
|
+
x_plus_neg_x = self.manifold.mobius_add(x, neg_x)
|
|
116
|
+
self.assertAlmostEqual(x_plus_neg_x[0], 0.0, places=5)
|
|
117
|
+
self.assertAlmostEqual(x_plus_neg_x[1], 0.0, places=5)
|
|
118
|
+
|
|
119
|
+
# Subtraction: x (-) x = 0
|
|
120
|
+
x_sub_x = self.manifold.mobius_sub(x, x)
|
|
121
|
+
self.assertAlmostEqual(x_sub_x[0], 0.0, places=5)
|
|
122
|
+
self.assertAlmostEqual(x_sub_x[1], 0.0, places=5)
|
|
123
|
+
|
|
124
|
+
def test_distance_and_geodesic_properties(self):
|
|
125
|
+
x = (0.0, 0.0)
|
|
126
|
+
y = (0.5, 0.0)
|
|
127
|
+
d_xy = self.manifold.distance(x, y)
|
|
128
|
+
# Distance from origin in Poincare disk: 2 * artanh(||y||) = 2 * artanh(0.5) = ln(3) ~ 1.0986
|
|
129
|
+
expected_d = 2.0 * math.atanh(0.5)
|
|
130
|
+
self.assertAlmostEqual(d_xy, expected_d, places=5)
|
|
131
|
+
|
|
132
|
+
# Symmetry: d(x, y) == d(y, x)
|
|
133
|
+
d_yx = self.manifold.distance(y, x)
|
|
134
|
+
self.assertAlmostEqual(d_xy, d_yx, places=5)
|
|
135
|
+
|
|
136
|
+
# Triangle Inequality: d(x, z) <= d(x, y) + d(y, z)
|
|
137
|
+
z = (0.2, 0.6)
|
|
138
|
+
d_xz = self.manifold.distance(x, z)
|
|
139
|
+
d_yz = self.manifold.distance(y, z)
|
|
140
|
+
self.assertLessEqual(d_xz, d_xy + d_yz + 1e-6)
|
|
141
|
+
|
|
142
|
+
def test_exp_and_log_maps_roundtrip(self):
|
|
143
|
+
x = (0.2, -0.1)
|
|
144
|
+
v = (0.3, 0.4)
|
|
145
|
+
|
|
146
|
+
# Exponential map maps tangent vector to manifold
|
|
147
|
+
y = self.manifold.exp_map(x, v)
|
|
148
|
+
self.assertLess(math.sqrt(y[0]**2 + y[1]**2), 1.0)
|
|
149
|
+
|
|
150
|
+
# Logarithmic map recovers original tangent vector
|
|
151
|
+
v_recovered = self.manifold.log_map(x, y)
|
|
152
|
+
self.assertAlmostEqual(v_recovered[0], v[0], places=4)
|
|
153
|
+
self.assertAlmostEqual(v_recovered[1], v[1], places=4)
|
|
154
|
+
|
|
155
|
+
def test_geodesic_interpolation(self):
|
|
156
|
+
x = (-0.4, 0.2)
|
|
157
|
+
y = (0.3, -0.5)
|
|
158
|
+
|
|
159
|
+
# Midpoint gamma(0.5)
|
|
160
|
+
mid = self.manifold.geodesic_interpolate(x, y, 0.5)
|
|
161
|
+
d_total = self.manifold.distance(x, y)
|
|
162
|
+
d_x_mid = self.manifold.distance(x, mid)
|
|
163
|
+
d_mid_y = self.manifold.distance(mid, y)
|
|
164
|
+
|
|
165
|
+
self.assertAlmostEqual(d_x_mid, d_total / 2.0, places=4)
|
|
166
|
+
self.assertAlmostEqual(d_mid_y, d_total / 2.0, places=4)
|
|
167
|
+
|
|
168
|
+
def test_hyperbolic_tree_embedder(self):
|
|
169
|
+
embedder = HyperbolicTreeEmbedder(dimension=2, curvature=1.0, base_step_distance=1.0)
|
|
170
|
+
|
|
171
|
+
# Construct tree hierarchy
|
|
172
|
+
tree = {
|
|
173
|
+
"root": ["arch", "broker", "verifier"],
|
|
174
|
+
"arch": ["causal", "dialectical"],
|
|
175
|
+
"broker": ["policy", "runtime"],
|
|
176
|
+
"verifier": ["function", "composite"],
|
|
177
|
+
}
|
|
178
|
+
labels = {"root": "FableMode", "arch": "System3", "broker": "Broker", "verifier": "Verifiers"}
|
|
179
|
+
|
|
180
|
+
res = embedder.embed_hierarchy(tree, root_id="root", node_labels=labels)
|
|
181
|
+
self.assertEqual(res.total_nodes, 10)
|
|
182
|
+
self.assertEqual(res.tree_depth, 2)
|
|
183
|
+
self.assertEqual(res.root_id, "root")
|
|
184
|
+
|
|
185
|
+
# Root at origin
|
|
186
|
+
self.assertEqual(res.nodes["root"].coords, (0.0, 0.0))
|
|
187
|
+
|
|
188
|
+
# Children are strictly within Poincaré open disk
|
|
189
|
+
for nid, node in res.nodes.items():
|
|
190
|
+
norm = math.sqrt(sum(c * c for c in node.coords))
|
|
191
|
+
self.assertLess(norm, 1.0)
|
|
192
|
+
|
|
193
|
+
# Stress and distortion should be reasonably bounded
|
|
194
|
+
self.assertGreaterEqual(res.average_distortion, 0.0)
|
|
195
|
+
self.assertGreaterEqual(res.hierarchical_capacity_ratio, 1.0)
|
|
196
|
+
|
|
197
|
+
# Serialization roundtrip
|
|
198
|
+
d = res.to_dict()
|
|
199
|
+
restored = TreeEmbeddingResult.from_dict(d)
|
|
200
|
+
self.assertEqual(restored.total_nodes, res.total_nodes)
|
|
201
|
+
self.assertEqual(restored.root_id, res.root_id)
|
|
202
|
+
|
|
203
|
+
|
|
204
|
+
class TestKripkeModalModelChecker(unittest.TestCase):
|
|
205
|
+
"""Unit tests for Kripke Structure, Multi-World Semantics, and CTL Model Checking."""
|
|
206
|
+
|
|
207
|
+
def setUp(self):
|
|
208
|
+
self.ks = KripkeStructure(name="System3SafetyProtocol")
|
|
209
|
+
# Worlds
|
|
210
|
+
self.ks.add_world("s0_init", ["ready", "safe"], is_initial=True)
|
|
211
|
+
self.ks.add_world("s1_deliberating", ["safe", "locked"])
|
|
212
|
+
self.ks.add_world("s2_unlocked", ["safe", "can_execute"])
|
|
213
|
+
self.ks.add_world("s3_done", ["safe", "complete"])
|
|
214
|
+
self.ks.add_world("s_error", ["error"])
|
|
215
|
+
|
|
216
|
+
# Transitions (Safe path: s0 -> s1 -> s2 -> s3 -> s3; Error branch: s1 -> s_error)
|
|
217
|
+
self.ks.add_transition("s0_init", "s1_deliberating")
|
|
218
|
+
self.ks.add_transition("s1_deliberating", "s2_unlocked")
|
|
219
|
+
self.ks.add_transition("s2_unlocked", "s3_done")
|
|
220
|
+
self.ks.add_transition("s3_done", "s3_done") # Self loop
|
|
221
|
+
self.ks.add_transition("s_error", "s_error")
|
|
222
|
+
|
|
223
|
+
self.checker = KripkeModelChecker(self.ks)
|
|
224
|
+
|
|
225
|
+
def test_formula_parser(self):
|
|
226
|
+
f1 = FormulaParser.parse("AG(safe)")
|
|
227
|
+
self.assertEqual(f1.op, CTLOperator.AG)
|
|
228
|
+
self.assertEqual(f1.left.op, CTLOperator.ATOM)
|
|
229
|
+
self.assertEqual(f1.left.name, "safe")
|
|
230
|
+
|
|
231
|
+
f2 = FormulaParser.parse("and(ready, safe)")
|
|
232
|
+
self.assertEqual(f2.op, CTLOperator.AND)
|
|
233
|
+
self.assertEqual(f2.left.name, "ready")
|
|
234
|
+
self.assertEqual(f2.right.name, "safe")
|
|
235
|
+
|
|
236
|
+
f3 = FormulaParser.parse("E[safe U complete]")
|
|
237
|
+
self.assertEqual(f3.op, CTLOperator.EU)
|
|
238
|
+
self.assertEqual(f3.left.name, "safe")
|
|
239
|
+
self.assertEqual(f3.right.name, "complete")
|
|
240
|
+
|
|
241
|
+
f4 = FormulaParser.parse("box(safe)")
|
|
242
|
+
self.assertEqual(f4.op, CTLOperator.BOX)
|
|
243
|
+
|
|
244
|
+
def test_modal_operators_box_and_diamond(self):
|
|
245
|
+
# In s0_init, all successors (s1_deliberating) have 'safe' -> Box(safe) holds
|
|
246
|
+
res_box = self.checker.check("box(safe)", initial_world="s0_init")
|
|
247
|
+
self.assertTrue(res_box.is_satisfied)
|
|
248
|
+
|
|
249
|
+
# In s0_init, diamond(locked) holds because s1_deliberating has 'locked'
|
|
250
|
+
res_dia = self.checker.check("diamond(locked)", initial_world="s0_init")
|
|
251
|
+
self.assertTrue(res_dia.is_satisfied)
|
|
252
|
+
|
|
253
|
+
def test_ctl_temporal_invariants(self):
|
|
254
|
+
# 1. AG(safe) from s0_init should be TRUE (s_error is unreachable from s0_init)
|
|
255
|
+
res_ag = self.checker.check("AG(safe)", initial_world="s0_init")
|
|
256
|
+
self.assertTrue(res_ag.is_satisfied)
|
|
257
|
+
|
|
258
|
+
# 2. EF(complete) from s0_init should be TRUE (s0 -> s1 -> s2 -> s3)
|
|
259
|
+
res_ef = self.checker.check("EF(complete)", initial_world="s0_init")
|
|
260
|
+
self.assertTrue(res_ef.is_satisfied)
|
|
261
|
+
self.assertIsNotNone(res_ef.witness_path)
|
|
262
|
+
self.assertEqual(res_ef.witness_path[0], "s0_init")
|
|
263
|
+
self.assertEqual(res_ef.witness_path[-1], "s3_done")
|
|
264
|
+
|
|
265
|
+
# 3. AF(complete) from s0_init should be TRUE
|
|
266
|
+
res_af = self.checker.check("AF(complete)", initial_world="s0_init")
|
|
267
|
+
self.assertTrue(res_af.is_satisfied)
|
|
268
|
+
|
|
269
|
+
# 4. AX(locked) from s0_init should be TRUE (next state is s1_deliberating)
|
|
270
|
+
res_ax = self.checker.check("AX(locked)", initial_world="s0_init")
|
|
271
|
+
self.assertTrue(res_ax.is_satisfied)
|
|
272
|
+
|
|
273
|
+
# 5. E[safe U complete] from s0_init should be TRUE
|
|
274
|
+
res_eu = self.checker.check("E[safe U complete]", initial_world="s0_init")
|
|
275
|
+
self.assertTrue(res_eu.is_satisfied)
|
|
276
|
+
|
|
277
|
+
def test_violation_and_counterexample_trace(self):
|
|
278
|
+
# Add transition from s1_deliberating to s_error
|
|
279
|
+
self.ks.add_transition("s1_deliberating", "s_error")
|
|
280
|
+
|
|
281
|
+
# Now AG(safe) fails because s_error is reachable
|
|
282
|
+
res_ag_fail = self.checker.check("AG(safe)", initial_world="s0_init")
|
|
283
|
+
self.assertFalse(res_ag_fail.is_satisfied)
|
|
284
|
+
self.assertIsNotNone(res_ag_fail.counterexample_path)
|
|
285
|
+
self.assertEqual(res_ag_fail.counterexample_path, ["s0_init", "s1_deliberating", "s_error"])
|
|
286
|
+
|
|
287
|
+
# Serialization
|
|
288
|
+
d = res_ag_fail.to_dict()
|
|
289
|
+
restored = ModelCheckResult.from_dict(d)
|
|
290
|
+
self.assertFalse(restored.is_satisfied)
|
|
291
|
+
self.assertEqual(restored.counterexample_path, ["s0_init", "s1_deliberating", "s_error"])
|
|
292
|
+
|
|
293
|
+
|
|
294
|
+
class TestFristonActiveInferenceEngine(unittest.TestCase):
|
|
295
|
+
"""Unit tests for Karl Friston's Active Inference & Variational Free Energy."""
|
|
296
|
+
|
|
297
|
+
def setUp(self):
|
|
298
|
+
self.model = create_default_architecture_pomdp()
|
|
299
|
+
self.engine = ActiveInferenceEngine(generative_model=self.model, policy_precision_gamma=16.0)
|
|
300
|
+
|
|
301
|
+
def test_model_initialization_and_normalization(self):
|
|
302
|
+
self.assertEqual(len(self.model.states), 4)
|
|
303
|
+
self.assertEqual(len(self.model.observations), 4)
|
|
304
|
+
self.assertEqual(len(self.model.actions), 4)
|
|
305
|
+
|
|
306
|
+
# Column sums of A matrix must be 1.0
|
|
307
|
+
for s_idx in range(len(self.model.states)):
|
|
308
|
+
col_sum = sum(self.model.a_matrix[o_idx][s_idx] for o_idx in range(len(self.model.observations)))
|
|
309
|
+
self.assertAlmostEqual(col_sum, 1.0, places=5)
|
|
310
|
+
|
|
311
|
+
def test_perception_free_energy_calculation(self):
|
|
312
|
+
# Ingest clean high throughput observation
|
|
313
|
+
f_val, comp_kl, acc_ll = self.engine.update_beliefs("HIGH_THROUGHPUT_CLEAN")
|
|
314
|
+
|
|
315
|
+
# Variational Free Energy F = Complexity - Accuracy
|
|
316
|
+
self.assertAlmostEqual(f_val, comp_kl - acc_ll, places=5)
|
|
317
|
+
|
|
318
|
+
# Belief for OPTIMAL_DECOUPLED should dominate
|
|
319
|
+
opt_idx = self.model.states.index("OPTIMAL_DECOUPLED")
|
|
320
|
+
self.assertGreater(self.engine.current_beliefs[opt_idx], 0.70)
|
|
321
|
+
|
|
322
|
+
def test_action_selection_and_policy_ranking(self):
|
|
323
|
+
# Inject lock contention warning observation
|
|
324
|
+
report = self.engine.select_action(
|
|
325
|
+
observation="LOCK_CONTENTION_WARN",
|
|
326
|
+
candidate_policies=[
|
|
327
|
+
Policy(policy_id="p_shard", actions=["SHARD_WORKERS"]),
|
|
328
|
+
Policy(policy_id="p_refactor", actions=["REFACTOR_MUTEX"]),
|
|
329
|
+
Policy(policy_id="p_cas", actions=["APPLY_CAS_ISOLATION"]),
|
|
330
|
+
Policy(policy_id="p_benchmark", actions=["RUN_BENCHMARK"]),
|
|
331
|
+
]
|
|
332
|
+
)
|
|
333
|
+
|
|
334
|
+
self.assertEqual(report.current_observation, "LOCK_CONTENTION_WARN")
|
|
335
|
+
self.assertEqual(len(report.evaluated_policies), 4)
|
|
336
|
+
|
|
337
|
+
# Expected Free Energy should favor corrective action
|
|
338
|
+
self.assertIn(report.selected_action, ["SHARD_WORKERS", "REFACTOR_MUTEX", "APPLY_CAS_ISOLATION"])
|
|
339
|
+
self.assertIsNotNone(report.selected_policy)
|
|
340
|
+
self.assertTrue(report.selected_policy.is_optimal)
|
|
341
|
+
|
|
342
|
+
# Probabilities sum to 1.0
|
|
343
|
+
prob_sum = sum(p.probability for p in report.evaluated_policies)
|
|
344
|
+
self.assertAlmostEqual(prob_sum, 1.0, places=5)
|
|
345
|
+
|
|
346
|
+
# Serialization
|
|
347
|
+
d = report.to_dict()
|
|
348
|
+
restored = FreeEnergyReport.from_dict(d)
|
|
349
|
+
self.assertEqual(restored.current_observation, report.current_observation)
|
|
350
|
+
self.assertEqual(restored.selected_action, report.selected_action)
|
|
351
|
+
|
|
352
|
+
|
|
353
|
+
class TestGodelianProofOracle(unittest.TestCase):
|
|
354
|
+
"""Unit tests for Gödelian Proof Oracle and Curry-Howard Constructive Type Checker."""
|
|
355
|
+
|
|
356
|
+
def setUp(self):
|
|
357
|
+
self.oracle = ProofOracle(max_search_depth=6)
|
|
358
|
+
|
|
359
|
+
def test_curry_howard_tautologies(self):
|
|
360
|
+
A = Prop("A")
|
|
361
|
+
B = Prop("B")
|
|
362
|
+
|
|
363
|
+
# 1. Identity / Modus Ponens Base: A -> A
|
|
364
|
+
# Proof: \x: A. x
|
|
365
|
+
proof_id = Lam("x", A, Var("x"))
|
|
366
|
+
self.assertTrue(CurryHowardVerifier.check_type(proof_id, Implies(A, A)))
|
|
367
|
+
|
|
368
|
+
# 2. Conjunction Commutativity: (A /\ B) -> (B /\ A)
|
|
369
|
+
# Proof: \p: (A /\ B). <snd p, fst p>
|
|
370
|
+
p_type = And(A, B)
|
|
371
|
+
proof_comm = Lam("p", p_type, Pair(Snd(Var("p")), Fst(Var("p"))))
|
|
372
|
+
self.assertTrue(CurryHowardVerifier.check_type(proof_comm, Implies(p_type, And(B, A))))
|
|
373
|
+
|
|
374
|
+
# 3. Disjunction Commutativity: (A \/ B) -> (B \/ A)
|
|
375
|
+
# Proof: \s: (A \/ B). case s of inl a => inr a | inr b => inl b
|
|
376
|
+
s_type = Or(A, B)
|
|
377
|
+
target_sum = Or(B, A)
|
|
378
|
+
proof_or_comm = Lam(
|
|
379
|
+
"s", s_type,
|
|
380
|
+
Case(
|
|
381
|
+
Var("s"),
|
|
382
|
+
"a", Inr(Var("a"), target_sum),
|
|
383
|
+
"b", Inl(Var("b"), target_sum),
|
|
384
|
+
)
|
|
385
|
+
)
|
|
386
|
+
self.assertTrue(CurryHowardVerifier.check_type(proof_or_comm, Implies(s_type, target_sum)))
|
|
387
|
+
|
|
388
|
+
def test_automatic_tactic_synthesis(self):
|
|
389
|
+
# Auto-prove A -> (B -> A)
|
|
390
|
+
A = Prop("A")
|
|
391
|
+
B = Prop("B")
|
|
392
|
+
goal = Implies(A, Implies(B, A))
|
|
393
|
+
|
|
394
|
+
res = self.oracle.verify_proposition(goal)
|
|
395
|
+
self.assertEqual(res.status, ProofStatus.DECIDABLE_PROVED)
|
|
396
|
+
self.assertTrue(res.is_sound)
|
|
397
|
+
self.assertIsNotNone(res.proof_term)
|
|
398
|
+
|
|
399
|
+
# Auto-prove equality: safe == safe
|
|
400
|
+
eq_goal = Eq("safe", "safe")
|
|
401
|
+
res_eq = self.oracle.verify_proposition(eq_goal)
|
|
402
|
+
self.assertEqual(res_eq.status, ProofStatus.DECIDABLE_PROVED)
|
|
403
|
+
self.assertTrue(res_eq.is_sound)
|
|
404
|
+
|
|
405
|
+
def test_refutation_of_contradictory_claims(self):
|
|
406
|
+
A = Prop("A")
|
|
407
|
+
# Context has A and ~A (A -> Void)
|
|
408
|
+
# Claim: Void -> goal should succeed or refuting A
|
|
409
|
+
ctx = {"h1": A, "h2": Not(A)}
|
|
410
|
+
res = self.oracle.verify_proposition(claim="P", context=ctx)
|
|
411
|
+
self.assertEqual(res.status, ProofStatus.DECIDABLE_PROVED) # Proved via ex falso quodlibet from context contradiction
|
|
412
|
+
|
|
413
|
+
def test_godelian_undecidability_and_paradox_detection(self):
|
|
414
|
+
# 1. Liar Paradox claim
|
|
415
|
+
res_liar = self.oracle.verify_proposition("Liar_Self_Negation_Paradox")
|
|
416
|
+
self.assertEqual(res_liar.status, ProofStatus.INDEPENDENT_UNDECIDABLE)
|
|
417
|
+
self.assertFalse(res_liar.is_sound)
|
|
418
|
+
self.assertIsNotNone(res_liar.undecidability_diagnostics)
|
|
419
|
+
|
|
420
|
+
# 2. Gödel sentence claim
|
|
421
|
+
res_godel = self.oracle.verify_proposition("Godel_Unprovable_Sentence")
|
|
422
|
+
self.assertEqual(res_godel.status, ProofStatus.INDEPENDENT_UNDECIDABLE)
|
|
423
|
+
self.assertIn("GODELIAN", res_godel.undecidability_diagnostics.get("boundary_type", ""))
|
|
424
|
+
|
|
425
|
+
# 3. Halting problem reduction
|
|
426
|
+
res_halt = self.oracle.verify_proposition("Turing_Diagonal_Halts_Predicate")
|
|
427
|
+
self.assertEqual(res_halt.status, ProofStatus.INDEPENDENT_UNDECIDABLE)
|
|
428
|
+
|
|
429
|
+
# Serialization
|
|
430
|
+
d = res_godel.to_dict()
|
|
431
|
+
restored = FormalProofResult.from_dict(d)
|
|
432
|
+
self.assertEqual(restored.status, ProofStatus.INDEPENDENT_UNDECIDABLE)
|
|
433
|
+
|
|
434
|
+
|
|
435
|
+
if __name__ == "__main__":
|
|
436
|
+
unittest.main(verbosity=2)
|