eyelang 1.7.16 → 1.7.17
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/examples/deep-taxonomy-10.eye +4 -13
- package/examples/deep-taxonomy-100.eye +4 -13
- package/examples/deep-taxonomy-1000.eye +4 -13
- package/examples/deep-taxonomy-10000.eye +4 -22
- package/examples/deep-taxonomy-100000.eye +4 -112
- package/examples/output/deep-taxonomy-10.eye +1 -1
- package/examples/output/deep-taxonomy-100.eye +1 -1
- package/examples/output/deep-taxonomy-1000.eye +1 -1
- package/examples/output/deep-taxonomy-10000.eye +1 -1
- package/examples/output/deep-taxonomy-100000.eye +1 -1
- package/package.json +1 -1
- package/src/builtins/control.js +11 -2
- package/src/cli.js +3 -5
- package/src/solver.js +89 -1
|
@@ -1,11 +1,8 @@
|
|
|
1
1
|
% =============================================================================================================================
|
|
2
|
-
% Deep Taxonomy - depth 10 - expanded N3-style eyelang
|
|
2
|
+
% Deep Taxonomy - depth 10 - expanded N3-style eyelang
|
|
3
3
|
%
|
|
4
|
-
% Adjacent rules mirror the Eyeling N3 deep-taxonomy chain.
|
|
5
|
-
%
|
|
6
|
-
% can prove terminal/report goals without overflowing the JavaScript call stack.
|
|
7
|
-
% Report/check rules use once/1 so successful checks do not backtrack into a
|
|
8
|
-
% long adjacent-only proof after a shorter checkpoint proof has succeeded.
|
|
4
|
+
% Adjacent rules mirror the Eyeling N3 deep-taxonomy chain. Each step derives
|
|
5
|
+
% the next taxonomy class together with two side labels.
|
|
9
6
|
% =============================================================================================================================
|
|
10
7
|
|
|
11
8
|
% Output declarations: materialize/2 selects the relations written to this example's golden output.
|
|
@@ -27,12 +24,6 @@ a(ind, n0).
|
|
|
27
24
|
is(test, true) :- once(a(ind, a2)).
|
|
28
25
|
a(?x, a2) :- a(?x, n10).
|
|
29
26
|
|
|
30
|
-
% Redundant checkpoint accelerators.
|
|
31
|
-
|
|
32
|
-
a(?x, n10) :- a(?x, n0).
|
|
33
|
-
a(?x, n4) :- a(?x, n0).
|
|
34
|
-
a(?x, n9) :- a(?x, n0).
|
|
35
|
-
|
|
36
27
|
% Adjacent N3-style taxonomy rules.
|
|
37
28
|
|
|
38
29
|
a(?x, n1) :- a(?x, n0).
|
|
@@ -98,7 +89,7 @@ arc(check6, "C6 OK - the success flag is raised only after the terminal class a2
|
|
|
98
89
|
answer(report, "The test succeeds: starting from one individual classified as n0, the rules eventually classify it as n10 and then as a2.") :-
|
|
99
90
|
once(is(test, true)).
|
|
100
91
|
|
|
101
|
-
reason(report, "The adjacent rules mirror the Eyeling N3 deep-taxonomy-10 chain
|
|
92
|
+
reason(report, "The adjacent rules mirror the Eyeling N3 deep-taxonomy-10 chain: each rule advances one taxonomy level and adds the matching side labels.") :-
|
|
102
93
|
once(a(ind, a2)),
|
|
103
94
|
once(is(test, true)).
|
|
104
95
|
|
|
@@ -1,11 +1,8 @@
|
|
|
1
1
|
% =============================================================================================================================
|
|
2
|
-
% Deep Taxonomy - depth 100 - expanded N3-style eyelang
|
|
2
|
+
% Deep Taxonomy - depth 100 - expanded N3-style eyelang
|
|
3
3
|
%
|
|
4
|
-
% Adjacent rules mirror the Eyeling N3 deep-taxonomy chain.
|
|
5
|
-
%
|
|
6
|
-
% can prove terminal/report goals without overflowing the JavaScript call stack.
|
|
7
|
-
% Report/check rules use once/1 so successful checks do not backtrack into a
|
|
8
|
-
% long adjacent-only proof after a shorter checkpoint proof has succeeded.
|
|
4
|
+
% Adjacent rules mirror the Eyeling N3 deep-taxonomy chain. Each step derives
|
|
5
|
+
% the next taxonomy class together with two side labels.
|
|
9
6
|
% =============================================================================================================================
|
|
10
7
|
|
|
11
8
|
% Output declarations: materialize/2 selects the relations written to this example's golden output.
|
|
@@ -27,12 +24,6 @@ a(ind, n0).
|
|
|
27
24
|
is(test, true) :- once(a(ind, a2)).
|
|
28
25
|
a(?x, a2) :- a(?x, n100).
|
|
29
26
|
|
|
30
|
-
% Redundant checkpoint accelerators.
|
|
31
|
-
|
|
32
|
-
a(?x, n100) :- a(?x, n0).
|
|
33
|
-
a(?x, n49) :- a(?x, n0).
|
|
34
|
-
a(?x, n99) :- a(?x, n0).
|
|
35
|
-
|
|
36
27
|
% Adjacent N3-style taxonomy rules.
|
|
37
28
|
|
|
38
29
|
a(?x, n1) :- a(?x, n0).
|
|
@@ -368,7 +359,7 @@ arc(check6, "C6 OK - the success flag is raised only after the terminal class a2
|
|
|
368
359
|
answer(report, "The test succeeds: starting from one individual classified as n0, the rules eventually classify it as n100 and then as a2.") :-
|
|
369
360
|
once(is(test, true)).
|
|
370
361
|
|
|
371
|
-
reason(report, "The adjacent rules mirror the Eyeling N3 deep-taxonomy-100 chain
|
|
362
|
+
reason(report, "The adjacent rules mirror the Eyeling N3 deep-taxonomy-100 chain: each rule advances one taxonomy level and adds the matching side labels.") :-
|
|
372
363
|
once(a(ind, a2)),
|
|
373
364
|
once(is(test, true)).
|
|
374
365
|
|
|
@@ -1,11 +1,8 @@
|
|
|
1
1
|
% =============================================================================================================================
|
|
2
|
-
% Deep Taxonomy - depth 1000 - expanded N3-style eyelang
|
|
2
|
+
% Deep Taxonomy - depth 1000 - expanded N3-style eyelang
|
|
3
3
|
%
|
|
4
|
-
% Adjacent rules mirror the Eyeling N3 deep-taxonomy chain.
|
|
5
|
-
%
|
|
6
|
-
% can prove terminal/report goals without overflowing the JavaScript call stack.
|
|
7
|
-
% Report/check rules use once/1 so successful checks do not backtrack into a
|
|
8
|
-
% long adjacent-only proof after a shorter checkpoint proof has succeeded.
|
|
4
|
+
% Adjacent rules mirror the Eyeling N3 deep-taxonomy chain. Each step derives
|
|
5
|
+
% the next taxonomy class together with two side labels.
|
|
9
6
|
% =============================================================================================================================
|
|
10
7
|
|
|
11
8
|
% Output declarations: materialize/2 selects the relations written to this example's golden output.
|
|
@@ -27,12 +24,6 @@ a(ind, n0).
|
|
|
27
24
|
is(test, true) :- once(a(ind, a2)).
|
|
28
25
|
a(?x, a2) :- a(?x, n1000).
|
|
29
26
|
|
|
30
|
-
% Redundant checkpoint accelerators.
|
|
31
|
-
|
|
32
|
-
a(?x, n1000) :- a(?x, n0).
|
|
33
|
-
a(?x, n499) :- a(?x, n0).
|
|
34
|
-
a(?x, n999) :- a(?x, n0).
|
|
35
|
-
|
|
36
27
|
% Adjacent N3-style taxonomy rules.
|
|
37
28
|
|
|
38
29
|
a(?x, n1) :- a(?x, n0).
|
|
@@ -3068,7 +3059,7 @@ arc(check6, "C6 OK - the success flag is raised only after the terminal class a2
|
|
|
3068
3059
|
answer(report, "The test succeeds: starting from one individual classified as n0, the rules eventually classify it as n1000 and then as a2.") :-
|
|
3069
3060
|
once(is(test, true)).
|
|
3070
3061
|
|
|
3071
|
-
reason(report, "The adjacent rules mirror the Eyeling N3 deep-taxonomy-1000 chain
|
|
3062
|
+
reason(report, "The adjacent rules mirror the Eyeling N3 deep-taxonomy-1000 chain: each rule advances one taxonomy level and adds the matching side labels.") :-
|
|
3072
3063
|
once(a(ind, a2)),
|
|
3073
3064
|
once(is(test, true)).
|
|
3074
3065
|
|
|
@@ -1,11 +1,8 @@
|
|
|
1
1
|
% =============================================================================================================================
|
|
2
|
-
% Deep Taxonomy - depth 10000 - expanded N3-style eyelang
|
|
2
|
+
% Deep Taxonomy - depth 10000 - expanded N3-style eyelang
|
|
3
3
|
%
|
|
4
|
-
% Adjacent rules mirror the Eyeling N3 deep-taxonomy chain.
|
|
5
|
-
%
|
|
6
|
-
% can prove terminal/report goals without overflowing the JavaScript call stack.
|
|
7
|
-
% Report/check rules use once/1 so successful checks do not backtrack into a
|
|
8
|
-
% long adjacent-only proof after a shorter checkpoint proof has succeeded.
|
|
4
|
+
% Adjacent rules mirror the Eyeling N3 deep-taxonomy chain. Each step derives
|
|
5
|
+
% the next taxonomy class together with two side labels.
|
|
9
6
|
% =============================================================================================================================
|
|
10
7
|
|
|
11
8
|
% Output declarations: materialize/2 selects the relations written to this example's golden output.
|
|
@@ -27,21 +24,6 @@ a(ind, n0).
|
|
|
27
24
|
is(test, true) :- once(a(ind, a2)).
|
|
28
25
|
a(?x, a2) :- a(?x, n10000).
|
|
29
26
|
|
|
30
|
-
% Redundant checkpoint accelerators.
|
|
31
|
-
|
|
32
|
-
a(?x, n1000) :- a(?x, n0).
|
|
33
|
-
a(?x, n2000) :- a(?x, n1000).
|
|
34
|
-
a(?x, n3000) :- a(?x, n2000).
|
|
35
|
-
a(?x, n4000) :- a(?x, n3000).
|
|
36
|
-
a(?x, n5000) :- a(?x, n4000).
|
|
37
|
-
a(?x, n6000) :- a(?x, n5000).
|
|
38
|
-
a(?x, n7000) :- a(?x, n6000).
|
|
39
|
-
a(?x, n8000) :- a(?x, n7000).
|
|
40
|
-
a(?x, n9000) :- a(?x, n8000).
|
|
41
|
-
a(?x, n10000) :- a(?x, n9000).
|
|
42
|
-
a(?x, n4999) :- a(?x, n4000).
|
|
43
|
-
a(?x, n9999) :- a(?x, n9000).
|
|
44
|
-
|
|
45
27
|
% Adjacent N3-style taxonomy rules.
|
|
46
28
|
|
|
47
29
|
a(?x, n1) :- a(?x, n0).
|
|
@@ -30077,7 +30059,7 @@ arc(check6, "C6 OK - the success flag is raised only after the terminal class a2
|
|
|
30077
30059
|
answer(report, "The test succeeds: starting from one individual classified as n0, the rules eventually classify it as n10000 and then as a2.") :-
|
|
30078
30060
|
once(is(test, true)).
|
|
30079
30061
|
|
|
30080
|
-
reason(report, "The adjacent rules mirror the Eyeling N3 deep-taxonomy-10000 chain
|
|
30062
|
+
reason(report, "The adjacent rules mirror the Eyeling N3 deep-taxonomy-10000 chain: each rule advances one taxonomy level and adds the matching side labels.") :-
|
|
30081
30063
|
once(a(ind, a2)),
|
|
30082
30064
|
once(is(test, true)).
|
|
30083
30065
|
|
|
@@ -1,11 +1,8 @@
|
|
|
1
1
|
% =============================================================================================================================
|
|
2
|
-
% Deep Taxonomy - depth 100000 - expanded N3-style eyelang
|
|
2
|
+
% Deep Taxonomy - depth 100000 - expanded N3-style eyelang
|
|
3
3
|
%
|
|
4
|
-
% Adjacent rules mirror the Eyeling N3 deep-taxonomy chain.
|
|
5
|
-
%
|
|
6
|
-
% can prove terminal/report goals without overflowing the JavaScript call stack.
|
|
7
|
-
% Report/check rules use once/1 so successful checks do not backtrack into a
|
|
8
|
-
% long adjacent-only proof after a shorter checkpoint proof has succeeded.
|
|
4
|
+
% Adjacent rules mirror the Eyeling N3 deep-taxonomy chain. Each step derives
|
|
5
|
+
% the next taxonomy class together with two side labels.
|
|
9
6
|
% =============================================================================================================================
|
|
10
7
|
|
|
11
8
|
% Output declarations: materialize/2 selects the relations written to this example's golden output.
|
|
@@ -27,111 +24,6 @@ a(ind, n0).
|
|
|
27
24
|
is(test, true) :- once(a(ind, a2)).
|
|
28
25
|
a(?x, a2) :- a(?x, n100000).
|
|
29
26
|
|
|
30
|
-
% Redundant checkpoint accelerators.
|
|
31
|
-
|
|
32
|
-
a(?x, n1000) :- a(?x, n0).
|
|
33
|
-
a(?x, n2000) :- a(?x, n1000).
|
|
34
|
-
a(?x, n3000) :- a(?x, n2000).
|
|
35
|
-
a(?x, n4000) :- a(?x, n3000).
|
|
36
|
-
a(?x, n5000) :- a(?x, n4000).
|
|
37
|
-
a(?x, n6000) :- a(?x, n5000).
|
|
38
|
-
a(?x, n7000) :- a(?x, n6000).
|
|
39
|
-
a(?x, n8000) :- a(?x, n7000).
|
|
40
|
-
a(?x, n9000) :- a(?x, n8000).
|
|
41
|
-
a(?x, n10000) :- a(?x, n9000).
|
|
42
|
-
a(?x, n11000) :- a(?x, n10000).
|
|
43
|
-
a(?x, n12000) :- a(?x, n11000).
|
|
44
|
-
a(?x, n13000) :- a(?x, n12000).
|
|
45
|
-
a(?x, n14000) :- a(?x, n13000).
|
|
46
|
-
a(?x, n15000) :- a(?x, n14000).
|
|
47
|
-
a(?x, n16000) :- a(?x, n15000).
|
|
48
|
-
a(?x, n17000) :- a(?x, n16000).
|
|
49
|
-
a(?x, n18000) :- a(?x, n17000).
|
|
50
|
-
a(?x, n19000) :- a(?x, n18000).
|
|
51
|
-
a(?x, n20000) :- a(?x, n19000).
|
|
52
|
-
a(?x, n21000) :- a(?x, n20000).
|
|
53
|
-
a(?x, n22000) :- a(?x, n21000).
|
|
54
|
-
a(?x, n23000) :- a(?x, n22000).
|
|
55
|
-
a(?x, n24000) :- a(?x, n23000).
|
|
56
|
-
a(?x, n25000) :- a(?x, n24000).
|
|
57
|
-
a(?x, n26000) :- a(?x, n25000).
|
|
58
|
-
a(?x, n27000) :- a(?x, n26000).
|
|
59
|
-
a(?x, n28000) :- a(?x, n27000).
|
|
60
|
-
a(?x, n29000) :- a(?x, n28000).
|
|
61
|
-
a(?x, n30000) :- a(?x, n29000).
|
|
62
|
-
a(?x, n31000) :- a(?x, n30000).
|
|
63
|
-
a(?x, n32000) :- a(?x, n31000).
|
|
64
|
-
a(?x, n33000) :- a(?x, n32000).
|
|
65
|
-
a(?x, n34000) :- a(?x, n33000).
|
|
66
|
-
a(?x, n35000) :- a(?x, n34000).
|
|
67
|
-
a(?x, n36000) :- a(?x, n35000).
|
|
68
|
-
a(?x, n37000) :- a(?x, n36000).
|
|
69
|
-
a(?x, n38000) :- a(?x, n37000).
|
|
70
|
-
a(?x, n39000) :- a(?x, n38000).
|
|
71
|
-
a(?x, n40000) :- a(?x, n39000).
|
|
72
|
-
a(?x, n41000) :- a(?x, n40000).
|
|
73
|
-
a(?x, n42000) :- a(?x, n41000).
|
|
74
|
-
a(?x, n43000) :- a(?x, n42000).
|
|
75
|
-
a(?x, n44000) :- a(?x, n43000).
|
|
76
|
-
a(?x, n45000) :- a(?x, n44000).
|
|
77
|
-
a(?x, n46000) :- a(?x, n45000).
|
|
78
|
-
a(?x, n47000) :- a(?x, n46000).
|
|
79
|
-
a(?x, n48000) :- a(?x, n47000).
|
|
80
|
-
a(?x, n49000) :- a(?x, n48000).
|
|
81
|
-
a(?x, n50000) :- a(?x, n49000).
|
|
82
|
-
a(?x, n51000) :- a(?x, n50000).
|
|
83
|
-
a(?x, n52000) :- a(?x, n51000).
|
|
84
|
-
a(?x, n53000) :- a(?x, n52000).
|
|
85
|
-
a(?x, n54000) :- a(?x, n53000).
|
|
86
|
-
a(?x, n55000) :- a(?x, n54000).
|
|
87
|
-
a(?x, n56000) :- a(?x, n55000).
|
|
88
|
-
a(?x, n57000) :- a(?x, n56000).
|
|
89
|
-
a(?x, n58000) :- a(?x, n57000).
|
|
90
|
-
a(?x, n59000) :- a(?x, n58000).
|
|
91
|
-
a(?x, n60000) :- a(?x, n59000).
|
|
92
|
-
a(?x, n61000) :- a(?x, n60000).
|
|
93
|
-
a(?x, n62000) :- a(?x, n61000).
|
|
94
|
-
a(?x, n63000) :- a(?x, n62000).
|
|
95
|
-
a(?x, n64000) :- a(?x, n63000).
|
|
96
|
-
a(?x, n65000) :- a(?x, n64000).
|
|
97
|
-
a(?x, n66000) :- a(?x, n65000).
|
|
98
|
-
a(?x, n67000) :- a(?x, n66000).
|
|
99
|
-
a(?x, n68000) :- a(?x, n67000).
|
|
100
|
-
a(?x, n69000) :- a(?x, n68000).
|
|
101
|
-
a(?x, n70000) :- a(?x, n69000).
|
|
102
|
-
a(?x, n71000) :- a(?x, n70000).
|
|
103
|
-
a(?x, n72000) :- a(?x, n71000).
|
|
104
|
-
a(?x, n73000) :- a(?x, n72000).
|
|
105
|
-
a(?x, n74000) :- a(?x, n73000).
|
|
106
|
-
a(?x, n75000) :- a(?x, n74000).
|
|
107
|
-
a(?x, n76000) :- a(?x, n75000).
|
|
108
|
-
a(?x, n77000) :- a(?x, n76000).
|
|
109
|
-
a(?x, n78000) :- a(?x, n77000).
|
|
110
|
-
a(?x, n79000) :- a(?x, n78000).
|
|
111
|
-
a(?x, n80000) :- a(?x, n79000).
|
|
112
|
-
a(?x, n81000) :- a(?x, n80000).
|
|
113
|
-
a(?x, n82000) :- a(?x, n81000).
|
|
114
|
-
a(?x, n83000) :- a(?x, n82000).
|
|
115
|
-
a(?x, n84000) :- a(?x, n83000).
|
|
116
|
-
a(?x, n85000) :- a(?x, n84000).
|
|
117
|
-
a(?x, n86000) :- a(?x, n85000).
|
|
118
|
-
a(?x, n87000) :- a(?x, n86000).
|
|
119
|
-
a(?x, n88000) :- a(?x, n87000).
|
|
120
|
-
a(?x, n89000) :- a(?x, n88000).
|
|
121
|
-
a(?x, n90000) :- a(?x, n89000).
|
|
122
|
-
a(?x, n91000) :- a(?x, n90000).
|
|
123
|
-
a(?x, n92000) :- a(?x, n91000).
|
|
124
|
-
a(?x, n93000) :- a(?x, n92000).
|
|
125
|
-
a(?x, n94000) :- a(?x, n93000).
|
|
126
|
-
a(?x, n95000) :- a(?x, n94000).
|
|
127
|
-
a(?x, n96000) :- a(?x, n95000).
|
|
128
|
-
a(?x, n97000) :- a(?x, n96000).
|
|
129
|
-
a(?x, n98000) :- a(?x, n97000).
|
|
130
|
-
a(?x, n99000) :- a(?x, n98000).
|
|
131
|
-
a(?x, n100000) :- a(?x, n99000).
|
|
132
|
-
a(?x, n49999) :- a(?x, n49000).
|
|
133
|
-
a(?x, n99999) :- a(?x, n99000).
|
|
134
|
-
|
|
135
27
|
% Adjacent N3-style taxonomy rules.
|
|
136
28
|
|
|
137
29
|
a(?x, n1) :- a(?x, n0).
|
|
@@ -300167,7 +300059,7 @@ arc(check6, "C6 OK - the success flag is raised only after the terminal class a2
|
|
|
300167
300059
|
answer(report, "The test succeeds: starting from one individual classified as n0, the rules eventually classify it as n100000 and then as a2.") :-
|
|
300168
300060
|
once(is(test, true)).
|
|
300169
300061
|
|
|
300170
|
-
reason(report, "The adjacent rules mirror the Eyeling N3 deep-taxonomy-100000 chain
|
|
300062
|
+
reason(report, "The adjacent rules mirror the Eyeling N3 deep-taxonomy-100000 chain: each rule advances one taxonomy level and adds the matching side labels.") :-
|
|
300171
300063
|
once(a(ind, a2)),
|
|
300172
300064
|
once(is(test, true)).
|
|
300173
300065
|
|
|
@@ -6,7 +6,7 @@ arc(check4, "C4 OK - the final taxonomy step from n9 to n10 was completed.").
|
|
|
6
6
|
arc(check5, "C5 OK - once n10 is reached, the terminal class a2 is derived.").
|
|
7
7
|
arc(check6, "C6 OK - the success flag is raised only after the terminal class a2 is present.").
|
|
8
8
|
answer(report, "The test succeeds: starting from one individual classified as n0, the rules eventually classify it as n10 and then as a2.").
|
|
9
|
-
reason(report, "The adjacent rules mirror the Eyeling N3 deep-taxonomy-10 chain
|
|
9
|
+
reason(report, "The adjacent rules mirror the Eyeling N3 deep-taxonomy-10 chain: each rule advances one taxonomy level and adds the matching side labels.").
|
|
10
10
|
checkPassed(report, check1).
|
|
11
11
|
checkPassed(report, check2).
|
|
12
12
|
checkPassed(report, check3).
|
|
@@ -6,7 +6,7 @@ arc(check4, "C4 OK - the final taxonomy step from n99 to n100 was completed.").
|
|
|
6
6
|
arc(check5, "C5 OK - once n100 is reached, the terminal class a2 is derived.").
|
|
7
7
|
arc(check6, "C6 OK - the success flag is raised only after the terminal class a2 is present.").
|
|
8
8
|
answer(report, "The test succeeds: starting from one individual classified as n0, the rules eventually classify it as n100 and then as a2.").
|
|
9
|
-
reason(report, "The adjacent rules mirror the Eyeling N3 deep-taxonomy-100 chain
|
|
9
|
+
reason(report, "The adjacent rules mirror the Eyeling N3 deep-taxonomy-100 chain: each rule advances one taxonomy level and adds the matching side labels.").
|
|
10
10
|
checkPassed(report, check1).
|
|
11
11
|
checkPassed(report, check2).
|
|
12
12
|
checkPassed(report, check3).
|
|
@@ -6,7 +6,7 @@ arc(check4, "C4 OK - the final taxonomy step from n999 to n1000 was completed.")
|
|
|
6
6
|
arc(check5, "C5 OK - once n1000 is reached, the terminal class a2 is derived.").
|
|
7
7
|
arc(check6, "C6 OK - the success flag is raised only after the terminal class a2 is present.").
|
|
8
8
|
answer(report, "The test succeeds: starting from one individual classified as n0, the rules eventually classify it as n1000 and then as a2.").
|
|
9
|
-
reason(report, "The adjacent rules mirror the Eyeling N3 deep-taxonomy-1000 chain
|
|
9
|
+
reason(report, "The adjacent rules mirror the Eyeling N3 deep-taxonomy-1000 chain: each rule advances one taxonomy level and adds the matching side labels.").
|
|
10
10
|
checkPassed(report, check1).
|
|
11
11
|
checkPassed(report, check2).
|
|
12
12
|
checkPassed(report, check3).
|
|
@@ -6,7 +6,7 @@ arc(check4, "C4 OK - the final taxonomy step from n9999 to n10000 was completed.
|
|
|
6
6
|
arc(check5, "C5 OK - once n10000 is reached, the terminal class a2 is derived.").
|
|
7
7
|
arc(check6, "C6 OK - the success flag is raised only after the terminal class a2 is present.").
|
|
8
8
|
answer(report, "The test succeeds: starting from one individual classified as n0, the rules eventually classify it as n10000 and then as a2.").
|
|
9
|
-
reason(report, "The adjacent rules mirror the Eyeling N3 deep-taxonomy-10000 chain
|
|
9
|
+
reason(report, "The adjacent rules mirror the Eyeling N3 deep-taxonomy-10000 chain: each rule advances one taxonomy level and adds the matching side labels.").
|
|
10
10
|
checkPassed(report, check1).
|
|
11
11
|
checkPassed(report, check2).
|
|
12
12
|
checkPassed(report, check3).
|
|
@@ -6,7 +6,7 @@ arc(check4, "C4 OK - the final taxonomy step from n99999 to n100000 was complete
|
|
|
6
6
|
arc(check5, "C5 OK - once n100000 is reached, the terminal class a2 is derived.").
|
|
7
7
|
arc(check6, "C6 OK - the success flag is raised only after the terminal class a2 is present.").
|
|
8
8
|
answer(report, "The test succeeds: starting from one individual classified as n0, the rules eventually classify it as n100000 and then as a2.").
|
|
9
|
-
reason(report, "The adjacent rules mirror the Eyeling N3 deep-taxonomy-100000 chain
|
|
9
|
+
reason(report, "The adjacent rules mirror the Eyeling N3 deep-taxonomy-100000 chain: each rule advances one taxonomy level and adds the matching side labels.").
|
|
10
10
|
checkPassed(report, check1).
|
|
11
11
|
checkPassed(report, check2).
|
|
12
12
|
checkPassed(report, check3).
|
package/package.json
CHANGED
package/src/builtins/control.js
CHANGED
|
@@ -11,15 +11,19 @@ function* notBuiltin({ solver, goal, env }) {
|
|
|
11
11
|
const limited = solver.cloneForInnerGoal(1);
|
|
12
12
|
let found = false;
|
|
13
13
|
for (const _ of limited.solve([goal.args[0]], env.clone(), 0)) { found = true; break; }
|
|
14
|
+
solver.absorbStatsFrom(limited);
|
|
14
15
|
if (!found) yield env;
|
|
15
16
|
}
|
|
16
17
|
|
|
17
18
|
function* onceBuiltin({ solver, goal, env }) {
|
|
18
19
|
const limited = solver.cloneForInnerGoal(1);
|
|
20
|
+
let first = null;
|
|
19
21
|
for (const answerEnv of limited.solve([goal.args[0]], env.clone(), 0)) {
|
|
20
|
-
|
|
22
|
+
first = answerEnv;
|
|
21
23
|
break;
|
|
22
24
|
}
|
|
25
|
+
solver.absorbStatsFrom(limited);
|
|
26
|
+
if (first) yield first;
|
|
23
27
|
}
|
|
24
28
|
|
|
25
29
|
function* forallBuiltin({ solver, goal, env }) {
|
|
@@ -28,7 +32,12 @@ function* forallBuiltin({ solver, goal, env }) {
|
|
|
28
32
|
const checker = solver.cloneForInnerGoal(1);
|
|
29
33
|
let ok = false;
|
|
30
34
|
for (const _ of checker.solve([goal.args[1]], answerEnv.clone(), 0)) { ok = true; break; }
|
|
31
|
-
|
|
35
|
+
solver.absorbStatsFrom(checker);
|
|
36
|
+
if (!ok) {
|
|
37
|
+
solver.absorbStatsFrom(generator);
|
|
38
|
+
return;
|
|
39
|
+
}
|
|
32
40
|
}
|
|
41
|
+
solver.absorbStatsFrom(generator);
|
|
33
42
|
yield env;
|
|
34
43
|
}
|
package/src/cli.js
CHANGED
|
@@ -103,13 +103,12 @@ async function runDefault(engine, program, options) {
|
|
|
103
103
|
const materializedKeys = new Set(goals.map((goal) => `${goal.name}/${goal.arity}`));
|
|
104
104
|
const facts = program.sourceFactLines(materializedKeys);
|
|
105
105
|
const lines = new Set();
|
|
106
|
-
let lastStats = null;
|
|
107
106
|
const registry = engine.getDefaultRegistry();
|
|
108
107
|
const explanation = options.proof ? await loadExplanation() : null;
|
|
108
|
+
const solver = new engine.Solver(program, { registry });
|
|
109
109
|
|
|
110
110
|
for (const goal of goals) {
|
|
111
|
-
|
|
112
|
-
|
|
111
|
+
solver.solutionsSeen = 0;
|
|
113
112
|
for (const env of solver.solve([goal], new engine.Env(), 0)) {
|
|
114
113
|
if (!engine.termIsGround(goal, env)) continue;
|
|
115
114
|
|
|
@@ -122,10 +121,9 @@ async function runDefault(engine, program, options) {
|
|
|
122
121
|
if (options.proof) writeExplanation(explanation, program, engine.copyResolved(goal, env), registry);
|
|
123
122
|
}
|
|
124
123
|
|
|
125
|
-
lastStats = solver.stats;
|
|
126
124
|
}
|
|
127
125
|
|
|
128
|
-
if (options.stats
|
|
126
|
+
if (options.stats) printStats(solver.stats);
|
|
129
127
|
}
|
|
130
128
|
|
|
131
129
|
function writeExplanation(explanation, program, resolved, registry) {
|
package/src/solver.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// Depth-first eyelang solver with builtin dispatch, memoization, and guarded recursion handling.
|
|
2
2
|
// Most semantic decisions still flow through unification; optimizations only select candidates earlier.
|
|
3
|
-
import { COMPOUND, Env, flattenConjunction, freshTerm, termToString, unify, variantTerms } from './term.js';
|
|
3
|
+
import { COMPOUND, Env, copyResolved, flattenConjunction, freshTerm, termIsGround, termToString, unify, variantTerms } from './term.js';
|
|
4
4
|
import { createDefaultRegistry } from './builtins/registry.js';
|
|
5
5
|
import { selectClauseCandidates } from './program.js';
|
|
6
6
|
|
|
@@ -19,6 +19,7 @@ export class Solver {
|
|
|
19
19
|
this.solutionsSeen = 0;
|
|
20
20
|
this.active = [];
|
|
21
21
|
this.memo = new Map();
|
|
22
|
+
this.groundChainSuccess = new Set();
|
|
22
23
|
this.stats = {
|
|
23
24
|
completed_goal_lists: 0,
|
|
24
25
|
solve_goals_calls: 0,
|
|
@@ -34,9 +35,21 @@ export class Solver {
|
|
|
34
35
|
cloneForInnerGoal(solutionLimit = this.solutionLimit) {
|
|
35
36
|
const solver = new Solver(this.program, { registry: this.registry, maxDepth: this.maxDepth, solutionLimit });
|
|
36
37
|
solver.memo = this.memo;
|
|
38
|
+
solver.groundChainSuccess = this.groundChainSuccess;
|
|
37
39
|
return solver;
|
|
38
40
|
}
|
|
39
41
|
|
|
42
|
+
absorbStatsFrom(child) {
|
|
43
|
+
if (!child || child === this || !child.stats) return;
|
|
44
|
+
for (const [key, value] of Object.entries(child.stats)) {
|
|
45
|
+
if (key === 'max_depth' || key === 'max_goal_count') {
|
|
46
|
+
this.stats[key] = Math.max(this.stats[key] ?? 0, value ?? 0);
|
|
47
|
+
} else {
|
|
48
|
+
this.stats[key] = (this.stats[key] ?? 0) + (value ?? 0);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
40
53
|
*solve(goals, env = new Env(), depth = 0) {
|
|
41
54
|
if (!Array.isArray(goals)) goals = [goals];
|
|
42
55
|
|
|
@@ -267,6 +280,7 @@ function pushMemoAnswerFrames(stack, entry, goal, rest, env, depth, active, solv
|
|
|
267
280
|
|
|
268
281
|
function pushUserGoalUncachedFrames(stack, solver, group, goal, rest, env, depth, active) {
|
|
269
282
|
if (activeVariantIn(goal, env, active)) return;
|
|
283
|
+
if (tryPushGroundChainFrames(stack, solver, group, goal, rest, env, depth, active)) return;
|
|
270
284
|
const candidates = selectClauseCandidates(group, goal, env);
|
|
271
285
|
const frames = [];
|
|
272
286
|
for (const pass of [candidates.primary, candidates.fallback]) {
|
|
@@ -294,6 +308,80 @@ function pushUserGoalUncachedFrames(stack, solver, group, goal, rest, env, depth
|
|
|
294
308
|
for (let i = frames.length - 1; i >= 0; i--) stack.push(frames[i]);
|
|
295
309
|
}
|
|
296
310
|
|
|
311
|
+
|
|
312
|
+
function tryPushGroundChainFrames(stack, solver, group, goal, rest, env, depth, active) {
|
|
313
|
+
// Compress deterministic ground single-goal chains such as deep taxonomy
|
|
314
|
+
// proofs: a(ind, n100000) -> a(ind, n99999) -> ... -> a(ind, n0).
|
|
315
|
+
// This is a search-control optimization only. It fires only while each step
|
|
316
|
+
// has exactly one matching clause and a single ground body goal; otherwise the
|
|
317
|
+
// normal clause path below remains authoritative.
|
|
318
|
+
if (!termIsGround(goal, env)) return false;
|
|
319
|
+
|
|
320
|
+
const baseEnv = env;
|
|
321
|
+
let currentGroup = group;
|
|
322
|
+
let currentGoal = copyResolved(goal, env);
|
|
323
|
+
let currentDepth = depth;
|
|
324
|
+
const currentEnv = new Env();
|
|
325
|
+
const seen = new Set();
|
|
326
|
+
|
|
327
|
+
while (true) {
|
|
328
|
+
// The compressed path is iterative and protected by `seen`, so it does not
|
|
329
|
+
// consume JavaScript recursion depth the way the ordinary solver path does.
|
|
330
|
+
// Keep recording the logical depth for diagnostics, but do not cut off long
|
|
331
|
+
// finite taxonomy chains with the recursive maxDepth guard.
|
|
332
|
+
if (solver.solutionsSeen >= solver.solutionLimit) return true;
|
|
333
|
+
solver.stats.max_depth = Math.max(solver.stats.max_depth, currentDepth);
|
|
334
|
+
const key = `${currentGoal.name}/${currentGoal.arity}:${termToString(currentGoal, currentEnv, true)}`;
|
|
335
|
+
if (seen.has(key)) return true;
|
|
336
|
+
if (activeVariantIn(currentGoal, currentEnv, active)) return true;
|
|
337
|
+
if (solver.groundChainSuccess.has(key)) {
|
|
338
|
+
rememberGroundChainSuccess(solver, seen);
|
|
339
|
+
stack.push({ kind: 'goals', goals: rest, env: baseEnv, depth: depth + 1, active });
|
|
340
|
+
return true;
|
|
341
|
+
}
|
|
342
|
+
seen.add(key);
|
|
343
|
+
|
|
344
|
+
const candidates = selectClauseCandidates(currentGroup, currentGoal, currentEnv);
|
|
345
|
+
const matches = [];
|
|
346
|
+
for (const pass of [candidates.primary, candidates.fallback]) {
|
|
347
|
+
for (const clause of pass) {
|
|
348
|
+
if (headCannotMatch(currentGoal, clause.head, currentEnv)) continue;
|
|
349
|
+
const id = nextFreshId();
|
|
350
|
+
const freshHead = freshTerm(clause.head, id);
|
|
351
|
+
const freshBody = clause.body.map((term) => freshTerm(term, id));
|
|
352
|
+
const next = new Env();
|
|
353
|
+
solver.stats.unify_calls++;
|
|
354
|
+
if (!unify(currentGoal, freshHead, next)) continue;
|
|
355
|
+
matches.push({ body: freshBody, env: next });
|
|
356
|
+
if (matches.length > 1) return false;
|
|
357
|
+
}
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
if (matches.length !== 1) return false;
|
|
361
|
+
const match = matches[0];
|
|
362
|
+
if (match.body.length === 0) {
|
|
363
|
+
rememberGroundChainSuccess(solver, seen);
|
|
364
|
+
stack.push({ kind: 'goals', goals: rest, env: baseEnv, depth: depth + 1, active });
|
|
365
|
+
return true;
|
|
366
|
+
}
|
|
367
|
+
if (match.body.length !== 1) return false;
|
|
368
|
+
const nextGoal = match.body[0];
|
|
369
|
+
if (nextGoal.type !== COMPOUND || !termIsGround(nextGoal, match.env)) return false;
|
|
370
|
+
const resolvedNextGoal = copyResolved(nextGoal, match.env);
|
|
371
|
+
const nextGroup = solver.program.findGroup(resolvedNextGoal.name, resolvedNextGoal.arity);
|
|
372
|
+
if (!nextGroup) return false;
|
|
373
|
+
|
|
374
|
+
currentGoal = resolvedNextGoal;
|
|
375
|
+
currentGroup = nextGroup;
|
|
376
|
+
currentDepth++;
|
|
377
|
+
}
|
|
378
|
+
}
|
|
379
|
+
|
|
380
|
+
|
|
381
|
+
function rememberGroundChainSuccess(solver, seen) {
|
|
382
|
+
for (const key of seen) solver.groundChainSuccess.add(key);
|
|
383
|
+
}
|
|
384
|
+
|
|
297
385
|
function rememberMemoAnswer(entry, goal, env) {
|
|
298
386
|
const answerArgs = goal.args.map((arg) => importResolved(arg, env));
|
|
299
387
|
const key = answerArgs.map((arg) => termToString(arg, new Env(), true)).join('\x1f');
|