eyelang 1.7.14 → 1.7.15
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.
- package/docs/guide.md +5 -0
- package/examples/cdcl-sat-solver.eye +65 -0
- package/examples/equality-saturation.eye +84 -0
- package/examples/knuth-bendix-completion.eye +55 -0
- package/examples/output/cdcl-sat-solver.eye +7 -0
- package/examples/output/equality-saturation.eye +5 -0
- package/examples/output/knuth-bendix-completion.eye +7 -0
- package/examples/output/partial-evaluator.eye +4 -0
- package/examples/output/register-allocation.eye +8 -0
- package/examples/partial-evaluator.eye +74 -0
- package/examples/register-allocation.eye +77 -0
- package/package.json +1 -1
- package/playground.html +5 -0
package/docs/guide.md
CHANGED
|
@@ -335,6 +335,7 @@ Use `holds/2` when you want to match the member term directly, for example `name
|
|
|
335
335
|
| [`canary-release.eye`](../examples/canary-release.eye) | Decides canary rollout or rollback. | [`output/canary-release.eye`](../examples/output/canary-release.eye) |
|
|
336
336
|
| [`cat-koko.eye`](../examples/cat-koko.eye) | Demonstrates named existential witnesses from a Cat Koko rule pattern. | [`output/cat-koko.eye`](../examples/output/cat-koko.eye) |
|
|
337
337
|
| [`catalan-convolution.eye`](../examples/catalan-convolution.eye) | Computes Catalan numbers by tabled convolution. | [`output/catalan-convolution.eye`](../examples/output/catalan-convolution.eye) |
|
|
338
|
+
| [`cdcl-sat-solver.eye`](../examples/cdcl-sat-solver.eye) | Simulates one CDCL conflict-analysis step with a learned clause and backjumped model. | [`output/cdcl-sat-solver.eye`](../examples/output/cdcl-sat-solver.eye) |
|
|
338
339
|
| [`chart-parser.eye`](../examples/chart-parser.eye) | Parses small sentences with a tabled chart parser. | [`output/chart-parser.eye`](../examples/output/chart-parser.eye) |
|
|
339
340
|
| [`clinical-trial-screening.eye`](../examples/clinical-trial-screening.eye) | Screens candidates for a trial. | [`output/clinical-trial-screening.eye`](../examples/output/clinical-trial-screening.eye) |
|
|
340
341
|
| [`collatz-1000.eye`](../examples/collatz-1000.eye) | Materializes Collatz trajectories for starts 1000 down to 1. | [`output/collatz-1000.eye`](../examples/output/collatz-1000.eye) |
|
|
@@ -370,6 +371,7 @@ Use `holds/2` when you want to match the member term directly, for example `name
|
|
|
370
371
|
| [`drone-corridor-planner.eye`](../examples/drone-corridor-planner.eye) | Plans bounded drone corridor routes. | [`output/drone-corridor-planner.eye`](../examples/output/drone-corridor-planner.eye) |
|
|
371
372
|
| [`easter-computus.eye`](../examples/easter-computus.eye) | Computes Gregorian Easter dates. | [`output/easter-computus.eye`](../examples/output/easter-computus.eye) |
|
|
372
373
|
| [`electrical-rc-filter.eye`](../examples/electrical-rc-filter.eye) | Sizes an RC low-pass filter. | [`output/electrical-rc-filter.eye`](../examples/output/electrical-rc-filter.eye) |
|
|
374
|
+
| [`equality-saturation.eye`](../examples/equality-saturation.eye) | Performs bounded equality saturation and extracts the cheapest equivalent expression. | [`output/equality-saturation.eye`](../examples/output/equality-saturation.eye) |
|
|
373
375
|
| [`epidemic-policy.eye`](../examples/epidemic-policy.eye) | Chooses policies from risk and social cost. | [`output/epidemic-policy.eye`](../examples/output/epidemic-policy.eye) |
|
|
374
376
|
| [`equivalence-classes-overlap-implies-same-class.eye`](../examples/equivalence-classes-overlap-implies-same-class.eye) | Packages the shared-member proof pattern for equivalence classes. | [`output/equivalence-classes-overlap-implies-same-class.eye`](../examples/output/equivalence-classes-overlap-implies-same-class.eye) |
|
|
375
377
|
| [`eulerian-path.eye`](../examples/eulerian-path.eye) | Finds an Eulerian path using each edge once. | [`output/eulerian-path.eye`](../examples/output/eulerian-path.eye) |
|
|
@@ -407,6 +409,7 @@ Use `holds/2` when you want to match the member term directly, for example `name
|
|
|
407
409
|
| [`intuitionistic-logic-kripke.eye`](../examples/intuitionistic-logic-kripke.eye) | Emulates intuitionistic Kripke forcing and constructive implication. | [`output/intuitionistic-logic-kripke.eye`](../examples/output/intuitionistic-logic-kripke.eye) |
|
|
408
410
|
| [`job-shop-scheduling.eye`](../examples/job-shop-scheduling.eye) | Searches a small job-shop schedule and minimizes makespan. | [`output/job-shop-scheduling.eye`](../examples/output/job-shop-scheduling.eye) |
|
|
409
411
|
| [`knapsack-optimization.eye`](../examples/knapsack-optimization.eye) | Optimizes a finite 0/1 knapsack pack with aggregation. | [`output/knapsack-optimization.eye`](../examples/output/knapsack-optimization.eye) |
|
|
412
|
+
| [`knuth-bendix-completion.eye`](../examples/knuth-bendix-completion.eye) | Checks bounded Knuth-Bendix-style critical pairs for joinability. | [`output/knuth-bendix-completion.eye`](../examples/output/knuth-bendix-completion.eye) |
|
|
410
413
|
| [`knowledge-engineering-alignment-flow.eye`](../examples/knowledge-engineering-alignment-flow.eye) | Specializes reusable alignment rules into a target-shaped flow view. | [`output/knowledge-engineering-alignment-flow.eye`](../examples/output/knowledge-engineering-alignment-flow.eye) |
|
|
411
414
|
| [`language.eye`](../examples/language.eye) | Shows the modern Eyelang surface syntax in one compact recursive graph example. | [`output/language.eye`](../examples/output/language.eye) |
|
|
412
415
|
| [`law-of-cosines.eye`](../examples/law-of-cosines.eye) | Computes a triangle side by cosine law. | [`output/law-of-cosines.eye`](../examples/output/law-of-cosines.eye) |
|
|
@@ -434,6 +437,7 @@ Use `holds/2` when you want to match the member term directly, for example `name
|
|
|
434
437
|
| [`odrl-dpv-risk-ranked.eye`](../examples/odrl-dpv-risk-ranked.eye) | Ranks data-policy risks and mitigations. | [`output/odrl-dpv-risk-ranked.eye`](../examples/output/odrl-dpv-risk-ranked.eye) |
|
|
435
438
|
| [`orbital-transfer-design.eye`](../examples/orbital-transfer-design.eye) | Designs a Hohmann orbital transfer. | [`output/orbital-transfer-design.eye`](../examples/output/orbital-transfer-design.eye) |
|
|
436
439
|
| [`path-discovery.eye`](../examples/path-discovery.eye) | Discovers bounded air-route paths. | [`output/path-discovery.eye`](../examples/output/path-discovery.eye) |
|
|
440
|
+
| [`partial-evaluator.eye`](../examples/partial-evaluator.eye) | Specializes tiny expression programs by folding static inputs into residual code. | [`output/partial-evaluator.eye`](../examples/output/partial-evaluator.eye) |
|
|
437
441
|
| [`peano-arithmetic.eye`](../examples/peano-arithmetic.eye) | Computes Peano addition, multiplication, and factorial. | [`output/peano-arithmetic.eye`](../examples/output/peano-arithmetic.eye) |
|
|
438
442
|
| [`peano-calculus.eye`](../examples/peano-calculus.eye) | Computes Peano addition, multiplication, and factorial. | [`output/peano-calculus.eye`](../examples/output/peano-calculus.eye) |
|
|
439
443
|
| [`peasant.eye`](../examples/peasant.eye) | Performs peasant multiplication and exponentiation. | [`output/peasant.eye`](../examples/output/peasant.eye) |
|
|
@@ -445,6 +449,7 @@ Use `holds/2` when you want to match the member term directly, for example `name
|
|
|
445
449
|
| [`proof-contrapositive.eye`](../examples/proof-contrapositive.eye) | Models proof by contrapositive. | [`output/proof-contrapositive.eye`](../examples/output/proof-contrapositive.eye) |
|
|
446
450
|
| [`quadratic-formula.eye`](../examples/quadratic-formula.eye) | Solves sample quadratic equations. | [`output/quadratic-formula.eye`](../examples/output/quadratic-formula.eye) |
|
|
447
451
|
| [`radioactive-decay.eye`](../examples/radioactive-decay.eye) | Computes radioactive decay over time. | [`output/radioactive-decay.eye`](../examples/output/radioactive-decay.eye) |
|
|
452
|
+
| [`register-allocation.eye`](../examples/register-allocation.eye) | Allocates temporaries to two registers with spilling by bounded graph-coloring search. | [`output/register-allocation.eye`](../examples/output/register-allocation.eye) |
|
|
448
453
|
| [`reusable-builtins.eye`](../examples/reusable-builtins.eye) | Tours reusable numeric, list, and string builtins. | [`output/reusable-builtins.eye`](../examples/output/reusable-builtins.eye) |
|
|
449
454
|
| [`riemann-hypothesis.eye`](../examples/riemann-hypothesis.eye) | Checks a finite catalogue of non-trivial zeta zeros against the Riemann-hypothesis condition. | [`output/riemann-hypothesis.eye`](../examples/output/riemann-hypothesis.eye) |
|
|
450
455
|
| [`route-planning.eye`](../examples/route-planning.eye) | Finds routes and records them as explicit route terms. | [`output/route-planning.eye`](../examples/output/route-planning.eye) |
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
% A tiny CDCL-style SAT trace with one learned clause.
|
|
2
|
+
%
|
|
3
|
+
% Industrial CDCL solvers use watched literals, mutable trails, non-chronological
|
|
4
|
+
% backjumping, clause databases, restarts, and activity heuristics. Eyelang has
|
|
5
|
+
% no mutable state or destructive trail updates, so this example models one small
|
|
6
|
+
% conflict-analysis episode as relations over immutable terms.
|
|
7
|
+
%
|
|
8
|
+
% Formula:
|
|
9
|
+
% c1: not(a) or c
|
|
10
|
+
% c2: not(c)
|
|
11
|
+
% c3: a or b
|
|
12
|
+
%
|
|
13
|
+
% Decision a=true forces c=true by c1, which conflicts with c2. Resolving the
|
|
14
|
+
% reason c1 with the conflict c2 learns not(a). After backjumping, learned
|
|
15
|
+
% not(a) forces a=false, c2 gives c=false, and c3 forces b=true.
|
|
16
|
+
|
|
17
|
+
materialize(cdclAnswer, 2).
|
|
18
|
+
|
|
19
|
+
clause(c1, [neg(a), pos(c)]).
|
|
20
|
+
clause(c2, [neg(c)]).
|
|
21
|
+
clause(c3, [pos(a), pos(b)]).
|
|
22
|
+
|
|
23
|
+
% Initial trail before conflict analysis.
|
|
24
|
+
initial_value(a, true, decision(level1)).
|
|
25
|
+
initial_value(c, true, implied_by(c1)).
|
|
26
|
+
|
|
27
|
+
% The current trail makes a literal true or false.
|
|
28
|
+
lit_true(pos(?var), ?value_rel) :- call_value(?value_rel, ?var, true, ?).
|
|
29
|
+
lit_true(neg(?var), ?value_rel) :- call_value(?value_rel, ?var, false, ?).
|
|
30
|
+
lit_false(pos(?var), ?value_rel) :- call_value(?value_rel, ?var, false, ?).
|
|
31
|
+
lit_false(neg(?var), ?value_rel) :- call_value(?value_rel, ?var, true, ?).
|
|
32
|
+
|
|
33
|
+
% Eyelang cannot pass predicates as first-class values, so this small dispatcher
|
|
34
|
+
% lets the same literal helpers inspect either the initial or final trail.
|
|
35
|
+
call_value(initial, ?var, ?value, ?reason) :- initial_value(?var, ?value, ?reason).
|
|
36
|
+
call_value(final, ?var, ?value, ?reason) :- final_value(?var, ?value, ?reason).
|
|
37
|
+
|
|
38
|
+
% A clause is conflicting when all of its literals are false under a trail.
|
|
39
|
+
conflict(?trail, ?clause) :-
|
|
40
|
+
clause(?clause, ?literals),
|
|
41
|
+
forall(member(?literal, ?literals), lit_false(?literal, ?trail)).
|
|
42
|
+
|
|
43
|
+
% The learned clause for this tiny implication graph is obtained by resolving
|
|
44
|
+
% the conflict clause not(c) with c's reason not(a) or c, yielding not(a).
|
|
45
|
+
learned_clause(l1, [neg(a)]).
|
|
46
|
+
learned_from(l1, resolve(c2, c1, pivot(c))).
|
|
47
|
+
|
|
48
|
+
% After backjumping, the learned unit clause fixes a=false. Then the original
|
|
49
|
+
% clauses imply c=false and b=true.
|
|
50
|
+
final_value(a, false, learned(l1)).
|
|
51
|
+
final_value(c, false, unit(c2)).
|
|
52
|
+
final_value(b, true, unit(c3)).
|
|
53
|
+
|
|
54
|
+
model_satisfies_clause(?trail, ?clause) :-
|
|
55
|
+
clause(?clause, ?literals),
|
|
56
|
+
member(?literal, ?literals),
|
|
57
|
+
lit_true(?literal, ?trail).
|
|
58
|
+
|
|
59
|
+
final_model_ok(ok) :- forall(clause(?name, ?), model_satisfies_clause(final, ?name)).
|
|
60
|
+
|
|
61
|
+
cdclAnswer(conflict_clause, ?clause) :- conflict(initial, ?clause).
|
|
62
|
+
cdclAnswer(learned_clause, ?literals) :- learned_clause(l1, ?literals).
|
|
63
|
+
cdclAnswer(learned_from, ?reason) :- learned_from(l1, ?reason).
|
|
64
|
+
cdclAnswer(final_value(?var), ?value) :- final_model_ok(ok), final_value(?var, ?value, ?).
|
|
65
|
+
cdclAnswer(note, "one learned clause makes the final model satisfy all original clauses") :- final_model_ok(ok).
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
% Bounded equality saturation over tiny arithmetic expression terms.
|
|
2
|
+
%
|
|
3
|
+
% Real equality-saturation engines use mutable e-graphs, union-find classes,
|
|
4
|
+
% congruence closure, rewrite scheduling, and cost-based extraction. Eyelang has
|
|
5
|
+
% none of those primitives, so this example simulates the idea relationally: it
|
|
6
|
+
% enumerates expressions reachable within a small rewrite-fuel bound, scores the
|
|
7
|
+
% generated terms, and extracts the cheapest equivalent expression.
|
|
8
|
+
%
|
|
9
|
+
% The point is not to be fast. The point is to show the declarative shape of an
|
|
10
|
+
% e-graph optimizer in a language that was not designed for it.
|
|
11
|
+
|
|
12
|
+
materialize(egraphAnswer, 2).
|
|
13
|
+
|
|
14
|
+
table(equivalent_at_depth, 3).
|
|
15
|
+
table(expr_cost, 2).
|
|
16
|
+
|
|
17
|
+
% Start expression:
|
|
18
|
+
% ((x + 0) * 1) + 2 * (1 + 2)
|
|
19
|
+
% The best bounded rewrite result should be x + 6.
|
|
20
|
+
expr(start, add(mul(add(x, 0), 1), mul(2, add(1, 2)))).
|
|
21
|
+
fuel(6).
|
|
22
|
+
|
|
23
|
+
% Directed rewrite rules. A true e-graph would keep equalities in equivalence
|
|
24
|
+
% classes. This bounded version uses oriented rewrites so search terminates.
|
|
25
|
+
rewrite(add(?x, 0), ?x).
|
|
26
|
+
rewrite(add(0, ?x), ?x).
|
|
27
|
+
rewrite(mul(?x, 1), ?x).
|
|
28
|
+
rewrite(mul(1, ?x), ?x).
|
|
29
|
+
rewrite(mul(?x, 0), 0).
|
|
30
|
+
rewrite(mul(0, ?x), 0).
|
|
31
|
+
|
|
32
|
+
% Constant folding and one distributivity rule make the search space less toyish.
|
|
33
|
+
rewrite(add(?a, ?b), ?c) :- add(?a, ?b, ?c).
|
|
34
|
+
rewrite(mul(?a, ?b), ?c) :- mul(?a, ?b, ?c).
|
|
35
|
+
rewrite(mul(?x, add(?y, ?z)), add(mul(?x, ?y), mul(?x, ?z))).
|
|
36
|
+
|
|
37
|
+
% Apply a rewrite at the root or inside one subterm.
|
|
38
|
+
rewrite_anywhere(?in, ?out) :- rewrite(?in, ?out).
|
|
39
|
+
rewrite_anywhere(add(?a, ?b), add(?new_a, ?b)) :- rewrite_anywhere(?a, ?new_a).
|
|
40
|
+
rewrite_anywhere(add(?a, ?b), add(?a, ?new_b)) :- rewrite_anywhere(?b, ?new_b).
|
|
41
|
+
rewrite_anywhere(mul(?a, ?b), mul(?new_a, ?b)) :- rewrite_anywhere(?a, ?new_a).
|
|
42
|
+
rewrite_anywhere(mul(?a, ?b), mul(?a, ?new_b)) :- rewrite_anywhere(?b, ?new_b).
|
|
43
|
+
|
|
44
|
+
% Fuel-bounded closure. Every depth represents exactly that many rewrite steps;
|
|
45
|
+
% candidate_expression/1 looks across all depths from zero to the fuel limit.
|
|
46
|
+
equivalent_at_depth(0, ?expr, ?expr).
|
|
47
|
+
equivalent_at_depth(?depth, ?expr, ?out) :-
|
|
48
|
+
gt(?depth, 0),
|
|
49
|
+
sub(?depth, 1, ?previous_depth),
|
|
50
|
+
equivalent_at_depth(?previous_depth, ?expr, ?mid),
|
|
51
|
+
rewrite_anywhere(?mid, ?out).
|
|
52
|
+
|
|
53
|
+
candidate_expression(?candidate) :-
|
|
54
|
+
expr(start, ?expr),
|
|
55
|
+
fuel(?fuel),
|
|
56
|
+
between(0, ?fuel, ?depth),
|
|
57
|
+
equivalent_at_depth(?depth, ?expr, ?candidate).
|
|
58
|
+
|
|
59
|
+
% A tiny cost model for extraction. Leaves cost 1; compound nodes cost 1 plus
|
|
60
|
+
% their children. The numeric range is deliberately bounded for the generated
|
|
61
|
+
% constants in this example.
|
|
62
|
+
expr_cost(x, 1).
|
|
63
|
+
expr_cost(?n, 1) :- between(0, 20, ?n).
|
|
64
|
+
expr_cost(add(?a, ?b), ?cost) :-
|
|
65
|
+
expr_cost(?a, ?a_cost),
|
|
66
|
+
expr_cost(?b, ?b_cost),
|
|
67
|
+
add(?a_cost, ?b_cost, ?children),
|
|
68
|
+
add(?children, 1, ?cost).
|
|
69
|
+
expr_cost(mul(?a, ?b), ?cost) :-
|
|
70
|
+
expr_cost(?a, ?a_cost),
|
|
71
|
+
expr_cost(?b, ?b_cost),
|
|
72
|
+
add(?a_cost, ?b_cost, ?children),
|
|
73
|
+
add(?children, 1, ?cost).
|
|
74
|
+
|
|
75
|
+
best_expression(?expr, ?cost) :-
|
|
76
|
+
aggregate_min([?candidate_cost, ?candidate], ?candidate,
|
|
77
|
+
(candidate_expression(?candidate), expr_cost(?candidate, ?candidate_cost)),
|
|
78
|
+
[?cost, ?expr], ?expr).
|
|
79
|
+
|
|
80
|
+
egraphAnswer(start, ?expr) :- expr(start, ?expr).
|
|
81
|
+
egraphAnswer(best, ?expr) :- best_expression(?expr, ?).
|
|
82
|
+
egraphAnswer(cost, ?cost) :- best_expression(?, ?cost).
|
|
83
|
+
egraphAnswer(candidate_count, ?count) :- countall(candidate_expression(?), ?count).
|
|
84
|
+
egraphAnswer(note, "bounded equality saturation extracts the cheapest term without a real e-graph") :- best_expression(?, ?).
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
% Bounded Knuth-Bendix-style completion for append/2 terms.
|
|
2
|
+
%
|
|
3
|
+
% Full Knuth-Bendix completion orients equations, generates all critical pairs,
|
|
4
|
+
% reduces them, and may add new rules until all overlaps are joinable. That is
|
|
5
|
+
% a difficult global search problem. This example keeps the recognizable shape
|
|
6
|
+
% but bounds the hard part: the rewrite system is fixed, and a small catalog of
|
|
7
|
+
% critical overlaps is checked for joinability by normalization.
|
|
8
|
+
|
|
9
|
+
materialize(kbAnswer, 2).
|
|
10
|
+
|
|
11
|
+
table(normal_form, 2).
|
|
12
|
+
|
|
13
|
+
% Oriented equations for a monoid-like append constructor.
|
|
14
|
+
% append(nil, x) -> x
|
|
15
|
+
% append(x, nil) -> x
|
|
16
|
+
% append(append(x,y),z)-> append(x, append(y,z))
|
|
17
|
+
% The third rule right-associates terms so normalization terminates here.
|
|
18
|
+
oriented_rule(left_identity, append(nil, ?x), ?x).
|
|
19
|
+
oriented_rule(right_identity, append(?x, nil), ?x).
|
|
20
|
+
oriented_rule(associate_right, append(append(?x, ?y), ?z), append(?x, append(?y, ?z))).
|
|
21
|
+
|
|
22
|
+
% One rewrite at the root or below an append node.
|
|
23
|
+
rewrite_once(?in, ?out, ?rule) :- oriented_rule(?rule, ?in, ?out).
|
|
24
|
+
rewrite_once(append(?a, ?b), append(?new_a, ?b), ?rule) :- rewrite_once(?a, ?new_a, ?rule).
|
|
25
|
+
rewrite_once(append(?a, ?b), append(?a, ?new_b), ?rule) :- rewrite_once(?b, ?new_b, ?rule).
|
|
26
|
+
|
|
27
|
+
% Normalization by repeated rewriting. The rules above are oriented so that the
|
|
28
|
+
% recursive search has a normal form for the bounded terms in this example.
|
|
29
|
+
normal_form(?term, ?term) :- not(rewrite_once(?term, ?, ?)).
|
|
30
|
+
normal_form(?term, ?normal) :- rewrite_once(?term, ?next, ?), normal_form(?next, ?normal).
|
|
31
|
+
|
|
32
|
+
% A few critical pairs that arise from overlapping the three oriented rules.
|
|
33
|
+
% Each pair records the two one-step reducts that must later normalize together.
|
|
34
|
+
critical_pair(left_identity_assoc,
|
|
35
|
+
append(a, b),
|
|
36
|
+
append(nil, append(a, b))).
|
|
37
|
+
critical_pair(right_identity_assoc,
|
|
38
|
+
append(a, b),
|
|
39
|
+
append(a, append(nil, b))).
|
|
40
|
+
critical_pair(nested_assoc,
|
|
41
|
+
append(append(a, append(b, c)), d),
|
|
42
|
+
append(append(a, b), append(c, d))).
|
|
43
|
+
|
|
44
|
+
joined_pair(?name) :-
|
|
45
|
+
critical_pair(?name, ?left, ?right),
|
|
46
|
+
normal_form(?left, ?normal),
|
|
47
|
+
normal_form(?right, ?normal).
|
|
48
|
+
|
|
49
|
+
sample_term(append(append(nil, append(a, nil)), append(b, c))).
|
|
50
|
+
|
|
51
|
+
kbAnswer(sample_normal_form, ?normal) :- sample_term(?term), normal_form(?term, ?normal).
|
|
52
|
+
kbAnswer(joined_critical_pair, ?name) :- joined_pair(?name).
|
|
53
|
+
kbAnswer(oriented_rule_count, ?count) :- countall(oriented_rule(?, ?, ?), ?count).
|
|
54
|
+
kbAnswer(joined_critical_pair_count, ?count) :- countall(joined_pair(?), ?count).
|
|
55
|
+
kbAnswer(note, "a bounded completion check proves the selected critical pairs join") :- joined_pair(nested_assoc).
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
cdclAnswer(conflict_clause, c2).
|
|
2
|
+
cdclAnswer(learned_clause, [neg(a)]).
|
|
3
|
+
cdclAnswer(learned_from, resolve(c2, c1, pivot(c))).
|
|
4
|
+
cdclAnswer(final_value(a), false).
|
|
5
|
+
cdclAnswer(final_value(c), false).
|
|
6
|
+
cdclAnswer(final_value(b), true).
|
|
7
|
+
cdclAnswer(note, "one learned clause makes the final model satisfy all original clauses").
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
kbAnswer(sample_normal_form, append(a, append(b, c))).
|
|
2
|
+
kbAnswer(joined_critical_pair, left_identity_assoc).
|
|
3
|
+
kbAnswer(joined_critical_pair, right_identity_assoc).
|
|
4
|
+
kbAnswer(joined_critical_pair, nested_assoc).
|
|
5
|
+
kbAnswer(oriented_rule_count, 3).
|
|
6
|
+
kbAnswer(joined_critical_pair_count, 3).
|
|
7
|
+
kbAnswer(note, "a bounded completion check proves the selected critical pairs join").
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
partialEvalAnswer(residual(poly_y), add(mul(const(10), var(y)), const(13))).
|
|
2
|
+
partialEvalAnswer(residual(static_branch), const(11)).
|
|
3
|
+
partialEvalAnswer(residual(dynamic_branch), if(var(flag), const(11), mul(var(y), const(2)))).
|
|
4
|
+
partialEvalAnswer(note, "static inputs are folded while dynamic variables remain as residual code").
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
registerAnswer(best_allocation, [bind(a, r1), bind(b, spill), bind(c, r2), bind(d, r1)]).
|
|
2
|
+
registerAnswer(spill_cost, 1).
|
|
3
|
+
registerAnswer(place(a), r1).
|
|
4
|
+
registerAnswer(place(b), spill).
|
|
5
|
+
registerAnswer(place(c), r2).
|
|
6
|
+
registerAnswer(place(d), r1).
|
|
7
|
+
registerAnswer(valid_allocation_count, 33).
|
|
8
|
+
registerAnswer(note, "the cheapest solution spills b to color the a-b-c triangle with two registers").
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
% A tiny partial evaluator for expression terms.
|
|
2
|
+
%
|
|
3
|
+
% Real partial evaluation can specialize interpreters, control unfolding, avoid
|
|
4
|
+
% code explosion, and even approach self-application. This bounded Eyelang
|
|
5
|
+
% version specializes a miniature expression language with known static inputs:
|
|
6
|
+
% constants are folded, known variables are substituted, and dynamic variables
|
|
7
|
+
% remain as residual code.
|
|
8
|
+
|
|
9
|
+
materialize(partialEvalAnswer, 2).
|
|
10
|
+
|
|
11
|
+
table(pe, 3).
|
|
12
|
+
|
|
13
|
+
% Expression language: const/1, bool/1, var/1, add/2, mul/2, and if/3.
|
|
14
|
+
% Static environments are lists of bind(Name, ResidualValue) terms.
|
|
15
|
+
program(poly_y,
|
|
16
|
+
add(mul(var(x), var(y)), add(var(x), const(3))),
|
|
17
|
+
[bind(x, const(10))]).
|
|
18
|
+
program(static_branch,
|
|
19
|
+
if(bool(true), add(var(x), const(1)), mul(var(y), const(999))),
|
|
20
|
+
[bind(x, const(10))]).
|
|
21
|
+
program(dynamic_branch,
|
|
22
|
+
if(var(flag), add(var(x), const(1)), mul(var(y), const(2))),
|
|
23
|
+
[bind(x, const(10))]).
|
|
24
|
+
|
|
25
|
+
lookup(?name, [bind(?name, ?value) | ?], ?value).
|
|
26
|
+
lookup(?name, [bind(?, ?) | ?rest], ?value) :- lookup(?name, ?rest, ?value).
|
|
27
|
+
|
|
28
|
+
known_var(?env, ?name, ?value) :- lookup(?name, ?env, ?value).
|
|
29
|
+
unknown_var(?env, ?name) :- not(known_var(?env, ?name, ?)).
|
|
30
|
+
|
|
31
|
+
pe(?, const(?n), const(?n)).
|
|
32
|
+
pe(?, bool(?b), bool(?b)).
|
|
33
|
+
pe(?env, var(?name), ?value) :- known_var(?env, ?name, ?value).
|
|
34
|
+
pe(?env, var(?name), var(?name)) :- unknown_var(?env, ?name).
|
|
35
|
+
|
|
36
|
+
% Constant folding for arithmetic when both residual operands became constants.
|
|
37
|
+
pe(?env, add(?left, ?right), const(?sum)) :-
|
|
38
|
+
pe(?env, ?left, const(?a)),
|
|
39
|
+
pe(?env, ?right, const(?b)),
|
|
40
|
+
add(?a, ?b, ?sum).
|
|
41
|
+
pe(?env, mul(?left, ?right), const(?product)) :-
|
|
42
|
+
pe(?env, ?left, const(?a)),
|
|
43
|
+
pe(?env, ?right, const(?b)),
|
|
44
|
+
mul(?a, ?b, ?product).
|
|
45
|
+
|
|
46
|
+
% Residual arithmetic when at least one operand remains dynamic.
|
|
47
|
+
pe(?env, add(?left, ?right), add(?left_residual, ?right_residual)) :-
|
|
48
|
+
pe(?env, ?left, ?left_residual),
|
|
49
|
+
pe(?env, ?right, ?right_residual),
|
|
50
|
+
not((eq(?left_residual, const(?a)), eq(?right_residual, const(?b)))).
|
|
51
|
+
pe(?env, mul(?left, ?right), mul(?left_residual, ?right_residual)) :-
|
|
52
|
+
pe(?env, ?left, ?left_residual),
|
|
53
|
+
pe(?env, ?right, ?right_residual),
|
|
54
|
+
not((eq(?left_residual, const(?a)), eq(?right_residual, const(?b)))).
|
|
55
|
+
|
|
56
|
+
% Static conditionals choose a branch; dynamic conditionals keep both residual
|
|
57
|
+
% branches after specializing their contents.
|
|
58
|
+
pe(?env, if(?cond, ?then, ?else), ?residual) :-
|
|
59
|
+
pe(?env, ?cond, bool(true)),
|
|
60
|
+
pe(?env, ?then, ?residual).
|
|
61
|
+
pe(?env, if(?cond, ?then, ?else), ?residual) :-
|
|
62
|
+
pe(?env, ?cond, bool(false)),
|
|
63
|
+
pe(?env, ?else, ?residual).
|
|
64
|
+
pe(?env, if(?cond, ?then, ?else), if(?cond_residual, ?then_residual, ?else_residual)) :-
|
|
65
|
+
pe(?env, ?cond, ?cond_residual),
|
|
66
|
+
not(eq(?cond_residual, bool(true))),
|
|
67
|
+
not(eq(?cond_residual, bool(false))),
|
|
68
|
+
pe(?env, ?then, ?then_residual),
|
|
69
|
+
pe(?env, ?else, ?else_residual).
|
|
70
|
+
|
|
71
|
+
residual_program(?name, ?residual) :- program(?name, ?expr, ?env), pe(?env, ?expr, ?residual).
|
|
72
|
+
|
|
73
|
+
partialEvalAnswer(residual(?name), ?residual) :- residual_program(?name, ?residual).
|
|
74
|
+
partialEvalAnswer(note, "static inputs are folded while dynamic variables remain as residual code") :- residual_program(poly_y, ?).
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
% Register allocation as bounded graph coloring with spilling.
|
|
2
|
+
%
|
|
3
|
+
% Production allocators combine liveness analysis, interference graphs, register
|
|
4
|
+
% classes, coalescing, rematerialization, and spill-code insertion. This Eyelang
|
|
5
|
+
% example reduces the problem to its logical core: enumerate assignments of a
|
|
6
|
+
% few temporaries to two registers or memory, reject register conflicts, and use
|
|
7
|
+
% aggregate_min/5 to choose the cheapest spill plan.
|
|
8
|
+
|
|
9
|
+
materialize(registerAnswer, 2).
|
|
10
|
+
|
|
11
|
+
% Two physical registers are available. The synthetic place spill means the
|
|
12
|
+
% temporary is kept in memory instead of a register.
|
|
13
|
+
register(r1).
|
|
14
|
+
register(r2).
|
|
15
|
+
place(?reg) :- register(?reg).
|
|
16
|
+
place(spill).
|
|
17
|
+
|
|
18
|
+
% Temporaries and the cost of spilling each one. The triangle a-b-c cannot be
|
|
19
|
+
% colored with only two registers, so at least one of them must spill.
|
|
20
|
+
temporary(a, 10).
|
|
21
|
+
temporary(b, 1).
|
|
22
|
+
temporary(c, 10).
|
|
23
|
+
temporary(d, 2).
|
|
24
|
+
|
|
25
|
+
interferes(a, b).
|
|
26
|
+
interferes(b, c).
|
|
27
|
+
interferes(c, a).
|
|
28
|
+
interferes(c, d).
|
|
29
|
+
|
|
30
|
+
% A candidate allocation is an immutable list of bindings. This is deliberately
|
|
31
|
+
% brute force: three choices for each of four temporaries.
|
|
32
|
+
candidate_allocation([
|
|
33
|
+
bind(a, ?a_place),
|
|
34
|
+
bind(b, ?b_place),
|
|
35
|
+
bind(c, ?c_place),
|
|
36
|
+
bind(d, ?d_place)
|
|
37
|
+
]) :-
|
|
38
|
+
place(?a_place),
|
|
39
|
+
place(?b_place),
|
|
40
|
+
place(?c_place),
|
|
41
|
+
place(?d_place).
|
|
42
|
+
|
|
43
|
+
assigned(?var, [[?var, ?place] | ?], ?place).
|
|
44
|
+
assigned(?var, [bind(?var, ?place) | ?], ?place).
|
|
45
|
+
assigned(?var, [bind(?, ?) | ?rest], ?place) :- assigned(?var, ?rest, ?place).
|
|
46
|
+
|
|
47
|
+
% A conflict exists only when both interfering temporaries choose the same real
|
|
48
|
+
% register. Spilled temporaries do not occupy registers.
|
|
49
|
+
allocation_conflict(?allocation) :-
|
|
50
|
+
interferes(?left, ?right),
|
|
51
|
+
assigned(?left, ?allocation, ?reg),
|
|
52
|
+
assigned(?right, ?allocation, ?reg),
|
|
53
|
+
register(?reg).
|
|
54
|
+
|
|
55
|
+
valid_allocation(?allocation) :-
|
|
56
|
+
candidate_allocation(?allocation),
|
|
57
|
+
not(allocation_conflict(?allocation)).
|
|
58
|
+
|
|
59
|
+
spill_cost_of_place(?var, spill, ?cost) :- temporary(?var, ?cost).
|
|
60
|
+
spill_cost_of_place(?var, ?reg, 0) :- temporary(?var, ?), register(?reg).
|
|
61
|
+
|
|
62
|
+
allocation_cost(?allocation, ?cost) :-
|
|
63
|
+
findall(?item_cost,
|
|
64
|
+
(member(bind(?var, ?place), ?allocation), spill_cost_of_place(?var, ?place, ?item_cost)),
|
|
65
|
+
?costs),
|
|
66
|
+
sum_list(?costs, ?cost).
|
|
67
|
+
|
|
68
|
+
best_allocation(?allocation, ?cost) :-
|
|
69
|
+
aggregate_min([?candidate_cost, ?candidate], ?candidate,
|
|
70
|
+
(valid_allocation(?candidate), allocation_cost(?candidate, ?candidate_cost)),
|
|
71
|
+
[?cost, ?allocation], ?allocation).
|
|
72
|
+
|
|
73
|
+
registerAnswer(best_allocation, ?allocation) :- best_allocation(?allocation, ?).
|
|
74
|
+
registerAnswer(spill_cost, ?cost) :- best_allocation(?, ?cost).
|
|
75
|
+
registerAnswer(place(?var), ?place) :- best_allocation(?allocation, ?), assigned(?var, ?allocation, ?place).
|
|
76
|
+
registerAnswer(valid_allocation_count, ?count) :- countall(valid_allocation(?), ?count).
|
|
77
|
+
registerAnswer(note, "the cheapest solution spills b to color the a-b-c triangle with two registers") :- best_allocation(?, ?).
|
package/package.json
CHANGED
package/playground.html
CHANGED
|
@@ -459,6 +459,7 @@
|
|
|
459
459
|
"canary-release",
|
|
460
460
|
"cat-koko",
|
|
461
461
|
"catalan-convolution",
|
|
462
|
+
"cdcl-sat-solver",
|
|
462
463
|
"chart-parser",
|
|
463
464
|
"clinical-trial-screening",
|
|
464
465
|
"collatz-1000",
|
|
@@ -494,6 +495,7 @@
|
|
|
494
495
|
"drone-corridor-planner",
|
|
495
496
|
"easter-computus",
|
|
496
497
|
"electrical-rc-filter",
|
|
498
|
+
"equality-saturation",
|
|
497
499
|
"epidemic-policy",
|
|
498
500
|
"equivalence-classes-overlap-implies-same-class",
|
|
499
501
|
"eulerian-path",
|
|
@@ -531,6 +533,7 @@
|
|
|
531
533
|
"intuitionistic-logic-kripke",
|
|
532
534
|
"job-shop-scheduling",
|
|
533
535
|
"knapsack-optimization",
|
|
536
|
+
"knuth-bendix-completion",
|
|
534
537
|
"knowledge-engineering-alignment-flow",
|
|
535
538
|
"language",
|
|
536
539
|
"law-of-cosines",
|
|
@@ -558,6 +561,7 @@
|
|
|
558
561
|
"odrl-dpv-risk-ranked",
|
|
559
562
|
"orbital-transfer-design",
|
|
560
563
|
"path-discovery",
|
|
564
|
+
"partial-evaluator",
|
|
561
565
|
"peano-arithmetic",
|
|
562
566
|
"peano-calculus",
|
|
563
567
|
"peasant",
|
|
@@ -569,6 +573,7 @@
|
|
|
569
573
|
"proof-contrapositive",
|
|
570
574
|
"quadratic-formula",
|
|
571
575
|
"radioactive-decay",
|
|
576
|
+
"register-allocation",
|
|
572
577
|
"reusable-builtins",
|
|
573
578
|
"riemann-hypothesis",
|
|
574
579
|
"route-planning",
|