eyeling 1.16.4 → 1.17.0

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.
@@ -1,57 +1,13 @@
1
- @prefix : <http://example.org/reals#> .
2
- @prefix log: <http://www.w3.org/2000/10/swap/log#> .
3
- @prefix xsd: <http://www.w3.org/2001/XMLSchema#> .
4
-
5
- :sqrt2Seq :term (1 "1.5"^^xsd:decimal) .
6
- :sqrt2Seq :error (0 "1"^^xsd:decimal) .
7
- :sqrt2Seq :error (1 "0.25"^^xsd:decimal) .
8
- :sqrt2Seq :delta (1 "0.5"^^xsd:decimal) .
9
- :sqrt2Seq log:outputString "n=0 x=1.0 delta=seed err=1\n" .
10
- :sqrt2Seq log:outputString "n=1 x=1.5 delta=0.5 err=0.25\n" .
11
- :sqrt2Seq :term (2 "1.4166666666666665"^^xsd:decimal) .
12
- :sqrt2Seq :error (2 "0.006944444444444198"^^xsd:decimal) .
13
- :sqrt2Seq :delta (2 "0.08333333333333348"^^xsd:decimal) .
14
- :sqrt2Seq log:outputString "n=2 x=1.4166666666666665 delta=0.08333333333333348 err=0.006944444444444198\n" .
15
- :sqrt2Seq :term (3 "1.4142156862745097"^^xsd:decimal) .
16
- :sqrt2Seq :error (3 "0.000006007304882427178"^^xsd:decimal) .
17
- :sqrt2Seq :delta (3 "0.002450980392156854"^^xsd:decimal) .
18
- :sqrt2Seq log:outputString "n=3 x=1.4142156862745097 delta=0.002450980392156854 err=0.000006007304882427178\n" .
19
- :sqrt2Seq :term (4 "1.4142135623746899"^^xsd:decimal) .
20
- :sqrt2Seq :error (4 "4.510614104447086e-12"^^xsd:double) .
21
- :sqrt2Seq :delta (4 "0.0000021238998197947723"^^xsd:decimal) .
22
- :sqrt2Seq :cauchyStep (4 true) .
23
- :sqrt2Seq log:outputString "n=4 x=1.4142135623746899 delta=0.0000021238998197947723 err=4.510614104447086e-12\n" .
24
- :sqrt2Seq :term (5 "1.414213562373095"^^xsd:decimal) .
25
- :sqrt2Seq :error (5 "4.440892098500626e-16"^^xsd:double) .
26
- :sqrt2Seq :delta (5 "1.5949463971764999e-12"^^xsd:double) .
27
- :sqrt2Seq :cauchyStep (5 true) .
28
- :sqrt2Seq log:outputString "n=5 x=1.414213562373095 delta=1.5949463971764999e-12 err=4.440892098500626e-16\n" .
29
- :sqrt2Seq :term (6 "1.414213562373095"^^xsd:decimal) .
30
- :sqrt2Seq :error (6 "4.440892098500626e-16"^^xsd:double) .
31
- :sqrt2Seq :delta (6 "0"^^xsd:decimal) .
32
- :sqrt2Seq :cauchyStep (6 true) .
33
- :sqrt2Seq log:outputString "n=6 x=1.414213562373095 delta=0 err=4.440892098500626e-16\n" .
34
- :sqrt2Seq :term (7 "1.414213562373095"^^xsd:decimal) .
35
- :sqrt2Seq :error (7 "4.440892098500626e-16"^^xsd:double) .
36
- :sqrt2Seq :delta (7 "0"^^xsd:decimal) .
37
- :sqrt2Seq :cauchyStep (7 true) .
38
- :sqrt2Seq log:outputString "n=7 x=1.414213562373095 delta=0 err=4.440892098500626e-16\n" .
39
- :sqrt2Seq :term (8 "1.414213562373095"^^xsd:decimal) .
40
- :sqrt2Seq :error (8 "4.440892098500626e-16"^^xsd:double) .
41
- :sqrt2Seq :delta (8 "0"^^xsd:decimal) .
42
- :sqrt2Seq :cauchyStep (8 true) .
43
- :sqrt2Seq log:outputString "n=8 x=1.414213562373095 delta=0 err=4.440892098500626e-16\n" .
44
- :sqrt2Seq :term (9 "1.414213562373095"^^xsd:decimal) .
45
- :sqrt2Seq :error (9 "4.440892098500626e-16"^^xsd:double) .
46
- :sqrt2Seq :delta (9 "0"^^xsd:decimal) .
47
- :sqrt2Seq :cauchyStep (9 true) .
48
- :sqrt2Seq log:outputString "n=9 x=1.414213562373095 delta=0 err=4.440892098500626e-16\n" .
49
- :sqrt2Seq :term (10 "1.414213562373095"^^xsd:decimal) .
50
- :sqrt2Seq :error (10 "4.440892098500626e-16"^^xsd:double) .
51
- :sqrt2Seq :delta (10 "0"^^xsd:decimal) .
52
- :sqrt2Seq :cauchyStep (10 true) .
53
- :sqrt2Real :approx "1.414213562373095"^^xsd:decimal .
54
- :sqrt2Seq log:outputString "n=10 x=1.414213562373095 delta=0 err=4.440892098500626e-16\n" .
55
- :sqrt2Real log:outputString "Approximation (at limit): sqrt2 ≈ 1.414213562373095\n" .
56
- :sqrt2Seq :boundedCauchyTail true .
57
- :sqrt2Seq log:outputString "Tail check: for i,j in (4..10), all |x_i - x_j| < 0.0001 (finite check)\n" .
1
+ Approximation (at limit): sqrt2 ≈ 1.414213562373095
2
+ n=0 x=1.0 delta=seed err=1
3
+ n=1 x=1.5 delta=0.5 err=0.25
4
+ n=2 x=1.4166666666666665 delta=0.08333333333333348 err=0.006944444444444198
5
+ n=3 x=1.4142156862745097 delta=0.002450980392156854 err=0.000006007304882427178
6
+ n=4 x=1.4142135623746899 delta=0.0000021238998197947723 err=4.510614104447086e-12
7
+ n=5 x=1.414213562373095 delta=1.5949463971764999e-12 err=4.440892098500626e-16
8
+ n=6 x=1.414213562373095 delta=0 err=4.440892098500626e-16
9
+ n=7 x=1.414213562373095 delta=0 err=4.440892098500626e-16
10
+ n=8 x=1.414213562373095 delta=0 err=4.440892098500626e-16
11
+ n=9 x=1.414213562373095 delta=0 err=4.440892098500626e-16
12
+ n=10 x=1.414213562373095 delta=0 err=4.440892098500626e-16
13
+ Tail check: for i,j in (4..10), all |x_i - x_j| < 0.0001 (finite check)
@@ -1,108 +1,31 @@
1
- @prefix : <http://example.org/dedekind#> .
2
- @prefix log: <http://www.w3.org/2000/10/swap/log#> .
3
- @prefix xsd: <http://www.w3.org/2001/XMLSchema#> .
4
-
5
- :QSample :square (-2 4) .
6
- :QSample :square (-1 1) .
7
- :QSample :square (-0.5 "0.25"^^xsd:decimal) .
8
- :QSample :square (-0.1 "0.010000000000000002"^^xsd:decimal) .
9
- :QSample :square (0 0) .
10
- :QSample :square (0.5 "0.25"^^xsd:decimal) .
11
- :QSample :square (1 1) .
12
- :QSample :square (1.3 "1.6900000000000002"^^xsd:decimal) .
13
- :QSample :square (1.4 "1.9599999999999997"^^xsd:decimal) .
14
- :QSample :square (1.41 "1.9880999999999998"^^xsd:decimal) .
15
- :QSample :square (1.414 "1.9993959999999997"^^xsd:decimal) .
16
- :QSample :square (1.4142 "1.9999616399999998"^^xsd:decimal) .
17
- :QSample :square (1.4143 "2.0002444899999996"^^xsd:decimal) .
18
- :QSample :square (1.42 "2.0164"^^xsd:decimal) .
19
- :QSample :square (1.5 "2.25"^^xsd:decimal) .
20
- :QSample :square (2 4) .
21
- :sqrt2Cut :seedLeft -2 .
22
- :sqrt2Cut :seedLeft -1 .
23
- :sqrt2Cut :seedLeft -0.5 .
24
- :sqrt2Cut :seedLeft -0.1 .
25
- :sqrt2Cut :seedLeft 0 .
26
- :sqrt2Cut :seedLeft 0.5 .
27
- :sqrt2Cut :seedLeft 1 .
28
- :sqrt2Cut :seedLeft 1.3 .
29
- :sqrt2Cut :seedLeft 1.4 .
30
- :sqrt2Cut :seedLeft 1.41 .
31
- :sqrt2Cut :seedLeft 1.414 .
32
- :sqrt2Cut :seedLeft 1.4142 .
33
- :sqrt2Cut :seedRight 1.4143 .
34
- :sqrt2Cut :seedRight 1.42 .
35
- :sqrt2Cut :seedRight 1.5 .
36
- :sqrt2Cut :seedRight 2 .
37
- :sqrt2Cut :successor (-2 -1) .
38
- :sqrt2Cut :constructedLeft -1 .
39
- :sqrt2Cut :successor (-1 "-0.5"^^xsd:decimal) .
40
- :sqrt2Cut :constructedLeft "-0.5"^^xsd:decimal .
41
- :sqrt2Cut :successor (-0.5 "-0.25"^^xsd:decimal) .
42
- :sqrt2Cut :constructedLeft "-0.25"^^xsd:decimal .
43
- :sqrt2Cut :successor (-0.1 "-0.05"^^xsd:decimal) .
44
- :sqrt2Cut :constructedLeft "-0.05"^^xsd:decimal .
45
- :sqrt2Cut :successor (0 1) .
46
- :sqrt2Cut :constructedLeft 1 .
47
- :sqrt2Cut :successor (0.5 "1.2"^^xsd:decimal) .
48
- :sqrt2Cut :constructedLeft "1.2"^^xsd:decimal .
49
- :sqrt2Cut :successor (1 "1.3333333333333333"^^xsd:decimal) .
50
- :sqrt2Cut :constructedLeft "1.3333333333333333"^^xsd:decimal .
51
- :sqrt2Cut :successor (1.3 "1.393939393939394"^^xsd:decimal) .
52
- :sqrt2Cut :constructedLeft "1.393939393939394"^^xsd:decimal .
53
- :sqrt2Cut :successor (1.4 "1.411764705882353"^^xsd:decimal) .
54
- :sqrt2Cut :constructedLeft "1.411764705882353"^^xsd:decimal .
55
- :sqrt2Cut :successor (1.41 "1.4134897360703813"^^xsd:decimal) .
56
- :sqrt2Cut :constructedLeft "1.4134897360703813"^^xsd:decimal .
57
- :sqrt2Cut :successor (1.414 "1.4141769185705917"^^xsd:decimal) .
58
- :sqrt2Cut :constructedLeft "1.4141769185705917"^^xsd:decimal .
59
- :sqrt2Cut :successor (1.4142 "1.4142112354285044"^^xsd:decimal) .
60
- :sqrt2Cut :constructedLeft "1.4142112354285044"^^xsd:decimal .
61
- :sqrt2Cut :hasSuccessor -2 .
62
- :sqrt2Cut :hasSuccessor -1 .
63
- :sqrt2Cut :hasSuccessor -0.5 .
64
- :sqrt2Cut :hasSuccessor -0.1 .
65
- :sqrt2Cut :hasSuccessor 0 .
66
- :sqrt2Cut :hasSuccessor 0.5 .
67
- :sqrt2Cut :hasSuccessor 1 .
68
- :sqrt2Cut :hasSuccessor 1.3 .
69
- :sqrt2Cut :hasSuccessor 1.4 .
70
- :sqrt2Cut :hasSuccessor 1.41 .
71
- :sqrt2Cut :hasSuccessor 1.414 .
72
- :sqrt2Cut :hasSuccessor 1.4142 .
73
- :sqrt2Cut :hasLeftWitness true .
74
- :sqrt2Cut :hasRightWitness true .
75
- :sqrt2Cut :properOnSample true .
76
- :sqrt2Cut log:outputString "q=-2 q^2=4 => LEFT (q<0 OR q^2<2)\n" .
77
- :sqrt2Cut log:outputString "q=-1 q^2=1 => LEFT (q<0 OR q^2<2)\n" .
78
- :sqrt2Cut log:outputString "q=-0.5 q^2=0.25 => LEFT (q<0 OR q^2<2)\n" .
79
- :sqrt2Cut log:outputString "q=-0.1 q^2=0.010000000000000002 => LEFT (q<0 OR q^2<2)\n" .
80
- :sqrt2Cut log:outputString "q=0 q^2=0 => LEFT (q<0 OR q^2<2)\n" .
81
- :sqrt2Cut log:outputString "q=0.5 q^2=0.25 => LEFT (q<0 OR q^2<2)\n" .
82
- :sqrt2Cut log:outputString "q=1 q^2=1 => LEFT (q<0 OR q^2<2)\n" .
83
- :sqrt2Cut log:outputString "q=1.3 q^2=1.6900000000000002 => LEFT (q<0 OR q^2<2)\n" .
84
- :sqrt2Cut log:outputString "q=1.4 q^2=1.9599999999999997 => LEFT (q<0 OR q^2<2)\n" .
85
- :sqrt2Cut log:outputString "q=1.41 q^2=1.9880999999999998 => LEFT (q<0 OR q^2<2)\n" .
86
- :sqrt2Cut log:outputString "q=1.414 q^2=1.9993959999999997 => LEFT (q<0 OR q^2<2)\n" .
87
- :sqrt2Cut log:outputString "q=1.4142 q^2=1.9999616399999998 => LEFT (q<0 OR q^2<2)\n" .
88
- :sqrt2Cut log:outputString "q=1.4143 q^2=2.0002444899999996 => RIGHT (q>=0 AND q^2>=2)\n" .
89
- :sqrt2Cut log:outputString "q=1.42 q^2=2.0164 => RIGHT (q>=0 AND q^2>=2)\n" .
90
- :sqrt2Cut log:outputString "q=1.5 q^2=2.25 => RIGHT (q>=0 AND q^2>=2)\n" .
91
- :sqrt2Cut log:outputString "q=2 q^2=4 => RIGHT (q>=0 AND q^2>=2)\n" .
92
- :sqrt2Cut log:outputString "successor: from -2 to -1 (s^2=1)\n" .
93
- :sqrt2Cut log:outputString "successor: from -1 to -0.5 (s^2=0.25)\n" .
94
- :sqrt2Cut log:outputString "successor: from -0.5 to -0.25 (s^2=0.0625)\n" .
95
- :sqrt2Cut log:outputString "successor: from -0.1 to -0.05 (s^2=0.0025000000000000005)\n" .
96
- :sqrt2Cut log:outputString "successor: from 0 to 1 (s^2=1)\n" .
97
- :sqrt2Cut log:outputString "successor: from 0.5 to 1.2 (s^2=1.44)\n" .
98
- :sqrt2Cut log:outputString "successor: from 1 to 1.3333333333333333 (s^2=1.7777777777777777)\n" .
99
- :sqrt2Cut log:outputString "successor: from 1.3 to 1.393939393939394 (s^2=1.9430670339761251)\n" .
100
- :sqrt2Cut log:outputString "successor: from 1.4 to 1.411764705882353 (s^2=1.9930795847750868)\n" .
101
- :sqrt2Cut log:outputString "successor: from 1.41 to 1.4134897360703813 (s^2=1.9979532339763162)\n" .
102
- :sqrt2Cut log:outputString "successor: from 1.414 to 1.4141769185705917 (s^2=1.9998963570178139)\n" .
103
- :sqrt2Cut log:outputString "successor: from 1.4142 to 1.4142112354285044 (s^2=1.9999934184122166)\n" .
104
- :sqrt2Cut log:outputString "Check: cut is proper on the sample (has LEFT and RIGHT witnesses)\n" .
105
- :sqrt2Cut :downwardClosedOnSample true .
106
- :sqrt2Cut :noMaxElementWitnessedForSeeds true .
107
- :sqrt2Cut log:outputString "Check: downward-closed on the sample (finite for-all test)\n" .
108
- :sqrt2Cut log:outputString "Check: no maximal element witnessed for all LEFT seed members (constructive successors)\n" .
1
+ q=-2 q^2=4 => LEFT (q<0 OR q^2<2)
2
+ q=-1 q^2=1 => LEFT (q<0 OR q^2<2)
3
+ q=-0.5 q^2=0.25 => LEFT (q<0 OR q^2<2)
4
+ q=-0.1 q^2=0.010000000000000002 => LEFT (q<0 OR q^2<2)
5
+ q=0 q^2=0 => LEFT (q<0 OR q^2<2)
6
+ q=0.5 q^2=0.25 => LEFT (q<0 OR q^2<2)
7
+ q=1 q^2=1 => LEFT (q<0 OR q^2<2)
8
+ q=1.3 q^2=1.6900000000000002 => LEFT (q<0 OR q^2<2)
9
+ q=1.4 q^2=1.9599999999999997 => LEFT (q<0 OR q^2<2)
10
+ q=1.41 q^2=1.9880999999999998 => LEFT (q<0 OR q^2<2)
11
+ q=1.414 q^2=1.9993959999999997 => LEFT (q<0 OR q^2<2)
12
+ q=1.4142 q^2=1.9999616399999998 => LEFT (q<0 OR q^2<2)
13
+ q=1.4143 q^2=2.0002444899999996 => RIGHT (q>=0 AND q^2>=2)
14
+ q=1.42 q^2=2.0164 => RIGHT (q>=0 AND q^2>=2)
15
+ q=1.5 q^2=2.25 => RIGHT (q>=0 AND q^2>=2)
16
+ q=2 q^2=4 => RIGHT (q>=0 AND q^2>=2)
17
+ successor: from -2 to -1 (s^2=1)
18
+ successor: from -1 to -0.5 (s^2=0.25)
19
+ successor: from -0.5 to -0.25 (s^2=0.0625)
20
+ successor: from -0.1 to -0.05 (s^2=0.0025000000000000005)
21
+ successor: from 0 to 1 (s^2=1)
22
+ successor: from 0.5 to 1.2 (s^2=1.44)
23
+ successor: from 1 to 1.3333333333333333 (s^2=1.7777777777777777)
24
+ successor: from 1.3 to 1.393939393939394 (s^2=1.9430670339761251)
25
+ successor: from 1.4 to 1.411764705882353 (s^2=1.9930795847750868)
26
+ successor: from 1.41 to 1.4134897360703813 (s^2=1.9979532339763162)
27
+ successor: from 1.414 to 1.4141769185705917 (s^2=1.9998963570178139)
28
+ successor: from 1.4142 to 1.4142112354285044 (s^2=1.9999934184122166)
29
+ Check: cut is proper on the sample (has LEFT and RIGHT witnesses)
30
+ Check: downward-closed on the sample (finite for-all test)
31
+ Check: no maximal element witnessed for all LEFT seed members (constructive successors)
@@ -0,0 +1,164 @@
1
+ # ===========================================================================
2
+ # ParcelLocker — One-time parcel pickup by a friend.
3
+ #
4
+ # This example shows how a person can let someone else collect a parcel without
5
+ # handing over their full shopping account. A one-time authorization is limited
6
+ # to one named person, one parcel, one locker, and one purpose: pickup. The
7
+ # locker may release the parcel, but the same authorization cannot be used to
8
+ # view billing details or redirect the parcel somewhere else.
9
+ # ===========================================================================
10
+
11
+ @prefix : <https://example.org/parcellocker#> .
12
+ @prefix log: <http://www.w3.org/2000/10/swap/log#> .
13
+
14
+ # -----
15
+ # Facts
16
+ # -----
17
+
18
+ :maya a :Person; :name "Maya" .
19
+ :noah a :Person; :name "Noah" .
20
+
21
+ :parcel123 a :Parcel;
22
+ :owner :maya;
23
+ :status :ReadyForPickup .
24
+
25
+ :lockerB17 a :Locker;
26
+ :site "Station West" .
27
+
28
+ :pickupToken a :PickupAuthorization;
29
+ :issuedBy :maya;
30
+ :delegate :noah;
31
+ :parcel :parcel123;
32
+ :locker :lockerB17;
33
+ :action :CollectParcel;
34
+ :purpose :PickupOnly;
35
+ :state :Active;
36
+ :reuse :SingleUse;
37
+ :billingAccess :None;
38
+ :redirectAllowed :No .
39
+
40
+ :pickupRequest a :Request;
41
+ :requester :noah;
42
+ :parcel :parcel123;
43
+ :locker :lockerB17;
44
+ :action :CollectParcel;
45
+ :purpose :PickupOnly .
46
+
47
+ # -----
48
+ # Logic
49
+ # -----
50
+
51
+ { :pickupToken :delegate ?who .
52
+ :pickupRequest :requester ?who . }
53
+ => { :case :checkC1 :Passed . } .
54
+
55
+ { :pickupToken :parcel ?parcel .
56
+ :pickupRequest :parcel ?parcel . }
57
+ => { :case :checkC2 :Passed . } .
58
+
59
+ { :pickupToken :locker ?locker .
60
+ :pickupRequest :locker ?locker . }
61
+ => { :case :checkC3 :Passed . } .
62
+
63
+ { :pickupToken :action ?action .
64
+ :pickupRequest :action ?action . }
65
+ => { :case :checkC4 :Passed . } .
66
+
67
+ { :pickupToken :purpose ?purpose .
68
+ :pickupRequest :purpose ?purpose . }
69
+ => { :case :checkC5 :Passed . } .
70
+
71
+ { :pickupToken :state :Active . }
72
+ => { :case :checkC6 :Passed . } .
73
+
74
+ { :pickupToken :reuse :SingleUse . }
75
+ => { :case :checkC7 :Passed . } .
76
+
77
+ { :parcel123 :status :ReadyForPickup . }
78
+ => { :case :checkC8 :Passed . } .
79
+
80
+ { :pickupToken :billingAccess :None . }
81
+ => { :case :checkC9 :Passed . } .
82
+
83
+ { :pickupToken :redirectAllowed :No . }
84
+ => { :case :checkC10 :Passed . } .
85
+
86
+ { :case :checkC1 :Passed .
87
+ :case :checkC2 :Passed .
88
+ :case :checkC3 :Passed .
89
+ :case :checkC4 :Passed .
90
+ :case :checkC5 :Passed .
91
+ :case :checkC6 :Passed .
92
+ :case :checkC7 :Passed .
93
+ :case :checkC8 :Passed .
94
+ :case :checkC9 :Passed .
95
+ :case :checkC10 :Passed . }
96
+ => { :case :decision :Permit . } .
97
+
98
+ # ------------------
99
+ # Presentation (ARC)
100
+ # ------------------
101
+
102
+ { :case :decision :Permit . }
103
+ => {
104
+ :out log:outputString "ParcelLocker — One-time parcel pickup by a friend\n\nAnswer\nPERMIT\nNoah may collect Maya's parcel from locker B17.\n\nReason Why\nMaya created a one-time authorization for Noah only, for this parcel only, at this locker only, and for pickup only. The token is active, the parcel is ready, and the same authorization does not reveal billing details or allow redirection.\n\nCheck\nC1 OK - requester matches the named delegate\nC2 OK - requested parcel matches the authorized parcel\nC3 OK - requested locker matches the authorized locker\nC4 OK - requested action is parcel collection\nC5 OK - requested purpose is pickup only\nC6 OK - authorization is active\nC7 OK - authorization is single-use\nC8 OK - parcel is ready for pickup\nC9 OK - billing details stay hidden\nC10 OK - parcel redirection is not allowed\n" .
105
+ } .
106
+
107
+ # ----------------
108
+ # Fail-loud checks
109
+ # ----------------
110
+
111
+ { :case :decision :Permit .
112
+ :pickupRequest :requester ?r .
113
+ :pickupToken :delegate ?d .
114
+ ?r log:notEqualTo ?d . }
115
+ => false .
116
+
117
+ { :case :decision :Permit .
118
+ :pickupRequest :parcel ?requested .
119
+ :pickupToken :parcel ?authorized .
120
+ ?requested log:notEqualTo ?authorized . }
121
+ => false .
122
+
123
+ { :case :decision :Permit .
124
+ :pickupRequest :locker ?requested .
125
+ :pickupToken :locker ?authorized .
126
+ ?requested log:notEqualTo ?authorized . }
127
+ => false .
128
+
129
+ { :case :decision :Permit .
130
+ :pickupRequest :action ?requested .
131
+ :pickupToken :action ?authorized .
132
+ ?requested log:notEqualTo ?authorized . }
133
+ => false .
134
+
135
+ { :case :decision :Permit .
136
+ :pickupRequest :purpose ?requested .
137
+ :pickupToken :purpose ?authorized .
138
+ ?requested log:notEqualTo ?authorized . }
139
+ => false .
140
+
141
+ { :case :decision :Permit .
142
+ :pickupToken :state ?state .
143
+ ?state log:notEqualTo :Active . }
144
+ => false .
145
+
146
+ { :case :decision :Permit .
147
+ :pickupToken :reuse ?reuse .
148
+ ?reuse log:notEqualTo :SingleUse . }
149
+ => false .
150
+
151
+ { :case :decision :Permit .
152
+ :parcel123 :status ?status .
153
+ ?status log:notEqualTo :ReadyForPickup . }
154
+ => false .
155
+
156
+ { :case :decision :Permit .
157
+ :pickupToken :billingAccess ?access .
158
+ ?access log:notEqualTo :None . }
159
+ => false .
160
+
161
+ { :case :decision :Permit .
162
+ :pickupToken :redirectAllowed ?redirect .
163
+ ?redirect log:notEqualTo :No . }
164
+ => false .
package/eyeling.js CHANGED
@@ -3210,7 +3210,7 @@ function evalBuiltin(goal, subst, facts, backRules, depth, varGen, maxResults) {
3210
3210
  // Schema: $s+ log:outputString $o+
3211
3211
  // Side-effecting output directive. As a builtin goal, we simply succeed
3212
3212
  // when both sides are bound and the object is a string literal.
3213
- // Actual printing is handled at the end of a reasoning run (see --strings).
3213
+ // Actual rendering is handled after reasoning, if any log:outputString facts exist.
3214
3214
  if (pv === LOG_NS + 'outputString') {
3215
3215
  // Require subject to be bound (not a variable) and object to be a concrete string literal.
3216
3216
  if (g.s instanceof Var) return [];
@@ -3938,7 +3938,6 @@ function main() {
3938
3938
  ` -e, --enforce-https Rewrite http:// IRIs to https:// for log dereferencing builtins.\n` +
3939
3939
  ` -h, --help Show this help and exit.\n` +
3940
3940
  ` -p, --proof-comments Enable proof explanations.\n` +
3941
- ` -r, --strings Print log:outputString strings (ordered by key), including via log:query.\n` +
3942
3941
  ` -s, --super-restricted Disable all builtins except => and <=.\n` +
3943
3942
  ` -t, --stream Stream derived triples as soon as they are derived.\n` +
3944
3943
  ` -v, --version Print version and exit.\n`;
@@ -3958,7 +3957,6 @@ function main() {
3958
3957
  }
3959
3958
 
3960
3959
  const showAst = argv.includes('--ast') || argv.includes('-a');
3961
- const outputStringsMode = argv.includes('--strings') || argv.includes('-r');
3962
3960
  const streamMode = argv.includes('--stream') || argv.includes('-t');
3963
3961
 
3964
3962
  // --enforce-https: rewrite http:// -> https:// for log dereferencing builtins
@@ -4045,28 +4043,30 @@ function main() {
4045
4043
  // ground-gated in the engine.
4046
4044
  const facts = triples.slice();
4047
4045
 
4048
- // If requested, print log:outputString values (ordered by subject key) and exit.
4049
- // Note: log:outputString values may depend on derived facts, so we must saturate first.
4050
- if (outputStringsMode) {
4051
- const hasQueries = Array.isArray(qrules) && qrules.length;
4052
-
4053
- // If log:query directives are present, the intended output may not be part of the
4054
- // saturated fact store (queries are output-selection statements). In that case,
4055
- // collect log:outputString triples from the instantiated query conclusions.
4056
- let outTriples;
4057
- if (hasQueries) {
4058
- const res = engine.forwardChainAndCollectLogQueryConclusions(facts, frules, brules, qrules, null, {
4059
- captureExplanations: engine.getProofCommentsEnabled(),
4060
- });
4061
- outTriples = res.queryTriples;
4062
- } else {
4063
- engine.forwardChain(facts, frules, brules, null, { captureExplanations: false });
4064
- outTriples = facts;
4065
- }
4046
+ const LOG_OUTPUT_STRING = 'http://www.w3.org/2000/10/swap/log#outputString';
4066
4047
 
4067
- const out = engine.collectOutputStringsFromFacts(outTriples, prefixes);
4068
- if (out) process.stdout.write(out);
4069
- process.exit(0);
4048
+ function programMayProduceOutputStrings(topLevelTriples, forwardRules, logQueryRules) {
4049
+ const hasOutputStringPredicate = (trs) =>
4050
+ Array.isArray(trs) &&
4051
+ trs.some(
4052
+ (tr) => tr && tr.p && tr.p.constructor && tr.p.constructor.name === 'Iri' && tr.p.value === LOG_OUTPUT_STRING,
4053
+ );
4054
+
4055
+ if (hasOutputStringPredicate(topLevelTriples)) return true;
4056
+ if (Array.isArray(forwardRules) && forwardRules.some((r) => hasOutputStringPredicate(r && r.conclusion)))
4057
+ return true;
4058
+ if (Array.isArray(logQueryRules) && logQueryRules.some((r) => hasOutputStringPredicate(r && r.conclusion)))
4059
+ return true;
4060
+ return false;
4061
+ }
4062
+
4063
+ function factsContainOutputStrings(triplesForOutput) {
4064
+ return (
4065
+ Array.isArray(triplesForOutput) &&
4066
+ triplesForOutput.some(
4067
+ (tr) => tr && tr.p && tr.p.constructor && tr.p.constructor.name === 'Iri' && tr.p.value === LOG_OUTPUT_STRING,
4068
+ )
4069
+ );
4070
4070
  }
4071
4071
 
4072
4072
  // In --stream mode we print prefixes *before* any derivations happen.
@@ -4154,7 +4154,10 @@ function main() {
4154
4154
  // Streaming mode: print (input) prefixes first, then print derived triples as soon as they are found.
4155
4155
  // Note: when log:query directives are present, we cannot stream output because
4156
4156
  // the selected results depend on the saturated closure.
4157
- if (streamMode && !(Array.isArray(qrules) && qrules.length)) {
4157
+ const hasQueries = Array.isArray(qrules) && qrules.length;
4158
+ const mayAutoRenderOutputStrings = programMayProduceOutputStrings(triples, frules, qrules);
4159
+
4160
+ if (streamMode && !hasQueries && !mayAutoRenderOutputStrings) {
4158
4161
  const usedInInput = prefixesUsedInInputTokens(toks, prefixes);
4159
4162
  const outPrefixes = restrictPrefixEnv(prefixes, usedInInput);
4160
4163
 
@@ -4189,8 +4192,6 @@ function main() {
4189
4192
  return;
4190
4193
  }
4191
4194
 
4192
- const hasQueries = Array.isArray(qrules) && qrules.length;
4193
-
4194
4195
  // Default (non-streaming):
4195
4196
  // - without log:query: derive everything first, then print only newly derived facts
4196
4197
  // - with log:query: derive everything first, then print only unique instantiated
@@ -4212,6 +4213,12 @@ function main() {
4212
4213
  outTriples = derived.map((df) => df.fact);
4213
4214
  }
4214
4215
 
4216
+ const renderedOutputTriples = hasQueries ? outTriples : facts;
4217
+ if (factsContainOutputStrings(renderedOutputTriples)) {
4218
+ process.stdout.write(engine.collectOutputStringsFromFacts(renderedOutputTriples, prefixes));
4219
+ return;
4220
+ }
4221
+
4215
4222
  const usedPrefixes = prefixes.prefixesUsedForOutput(outTriples);
4216
4223
 
4217
4224
  for (const [pfx, base] of usedPrefixes) {
@@ -4719,6 +4726,8 @@ const {
4719
4726
  MATH_NS,
4720
4727
  LOG_NS,
4721
4728
  SKOLEM_NS,
4729
+ MAX_LITERAL_TID_LEN,
4730
+ normalizeLiteralForTid,
4722
4731
  Literal,
4723
4732
  Iri,
4724
4733
  Var,
@@ -5627,7 +5636,18 @@ function __internCompoundTid(key) {
5627
5636
 
5628
5637
  function termFastKey(t) {
5629
5638
  // Atomic terms that already have a stable id.
5630
- if (t instanceof Iri || t instanceof Blank || t instanceof Literal) return t.__tid;
5639
+ if (t instanceof Iri || t instanceof Blank) return t.__tid;
5640
+
5641
+ if (t instanceof Literal) {
5642
+ // Very large literals intentionally skip global interning in prelude.js to
5643
+ // avoid retaining huge strings forever. Their per-object __tid is therefore
5644
+ // not value-stable, so using it here breaks duplicate detection for facts
5645
+ // such as long log:outputString blocks that are re-derived during forward
5646
+ // chaining. Fall back to a value-based key in that case.
5647
+ const norm = normalizeLiteralForTid(t.value);
5648
+ if (typeof norm === 'string' && norm.length > MAX_LITERAL_TID_LEN) return 'L:' + norm;
5649
+ return t.__tid;
5650
+ }
5631
5651
 
5632
5652
  // Structural fast key for strict-ground list terms.
5633
5653
  // We only index when every element has a fast key; otherwise return null.
@@ -10389,6 +10409,8 @@ module.exports = {
10389
10409
  RDF_JSON_DT,
10390
10410
  resolveIriRef,
10391
10411
  literalParts,
10412
+ normalizeLiteralForTid,
10413
+ MAX_LITERAL_TID_LEN,
10392
10414
  Term,
10393
10415
  Iri,
10394
10416
  Literal,
package/lib/builtins.js CHANGED
@@ -3198,7 +3198,7 @@ function evalBuiltin(goal, subst, facts, backRules, depth, varGen, maxResults) {
3198
3198
  // Schema: $s+ log:outputString $o+
3199
3199
  // Side-effecting output directive. As a builtin goal, we simply succeed
3200
3200
  // when both sides are bound and the object is a string literal.
3201
- // Actual printing is handled at the end of a reasoning run (see --strings).
3201
+ // Actual rendering is handled after reasoning, if any log:outputString facts exist.
3202
3202
  if (pv === LOG_NS + 'outputString') {
3203
3203
  // Require subject to be bound (not a variable) and object to be a concrete string literal.
3204
3204
  if (g.s instanceof Var) return [];
package/lib/cli.js CHANGED
@@ -71,7 +71,6 @@ function main() {
71
71
  ` -e, --enforce-https Rewrite http:// IRIs to https:// for log dereferencing builtins.\n` +
72
72
  ` -h, --help Show this help and exit.\n` +
73
73
  ` -p, --proof-comments Enable proof explanations.\n` +
74
- ` -r, --strings Print log:outputString strings (ordered by key), including via log:query.\n` +
75
74
  ` -s, --super-restricted Disable all builtins except => and <=.\n` +
76
75
  ` -t, --stream Stream derived triples as soon as they are derived.\n` +
77
76
  ` -v, --version Print version and exit.\n`;
@@ -91,7 +90,6 @@ function main() {
91
90
  }
92
91
 
93
92
  const showAst = argv.includes('--ast') || argv.includes('-a');
94
- const outputStringsMode = argv.includes('--strings') || argv.includes('-r');
95
93
  const streamMode = argv.includes('--stream') || argv.includes('-t');
96
94
 
97
95
  // --enforce-https: rewrite http:// -> https:// for log dereferencing builtins
@@ -178,28 +176,30 @@ function main() {
178
176
  // ground-gated in the engine.
179
177
  const facts = triples.slice();
180
178
 
181
- // If requested, print log:outputString values (ordered by subject key) and exit.
182
- // Note: log:outputString values may depend on derived facts, so we must saturate first.
183
- if (outputStringsMode) {
184
- const hasQueries = Array.isArray(qrules) && qrules.length;
185
-
186
- // If log:query directives are present, the intended output may not be part of the
187
- // saturated fact store (queries are output-selection statements). In that case,
188
- // collect log:outputString triples from the instantiated query conclusions.
189
- let outTriples;
190
- if (hasQueries) {
191
- const res = engine.forwardChainAndCollectLogQueryConclusions(facts, frules, brules, qrules, null, {
192
- captureExplanations: engine.getProofCommentsEnabled(),
193
- });
194
- outTriples = res.queryTriples;
195
- } else {
196
- engine.forwardChain(facts, frules, brules, null, { captureExplanations: false });
197
- outTriples = facts;
198
- }
179
+ const LOG_OUTPUT_STRING = 'http://www.w3.org/2000/10/swap/log#outputString';
180
+
181
+ function programMayProduceOutputStrings(topLevelTriples, forwardRules, logQueryRules) {
182
+ const hasOutputStringPredicate = (trs) =>
183
+ Array.isArray(trs) &&
184
+ trs.some(
185
+ (tr) => tr && tr.p && tr.p.constructor && tr.p.constructor.name === 'Iri' && tr.p.value === LOG_OUTPUT_STRING,
186
+ );
187
+
188
+ if (hasOutputStringPredicate(topLevelTriples)) return true;
189
+ if (Array.isArray(forwardRules) && forwardRules.some((r) => hasOutputStringPredicate(r && r.conclusion)))
190
+ return true;
191
+ if (Array.isArray(logQueryRules) && logQueryRules.some((r) => hasOutputStringPredicate(r && r.conclusion)))
192
+ return true;
193
+ return false;
194
+ }
199
195
 
200
- const out = engine.collectOutputStringsFromFacts(outTriples, prefixes);
201
- if (out) process.stdout.write(out);
202
- process.exit(0);
196
+ function factsContainOutputStrings(triplesForOutput) {
197
+ return (
198
+ Array.isArray(triplesForOutput) &&
199
+ triplesForOutput.some(
200
+ (tr) => tr && tr.p && tr.p.constructor && tr.p.constructor.name === 'Iri' && tr.p.value === LOG_OUTPUT_STRING,
201
+ )
202
+ );
203
203
  }
204
204
 
205
205
  // In --stream mode we print prefixes *before* any derivations happen.
@@ -287,7 +287,10 @@ function main() {
287
287
  // Streaming mode: print (input) prefixes first, then print derived triples as soon as they are found.
288
288
  // Note: when log:query directives are present, we cannot stream output because
289
289
  // the selected results depend on the saturated closure.
290
- if (streamMode && !(Array.isArray(qrules) && qrules.length)) {
290
+ const hasQueries = Array.isArray(qrules) && qrules.length;
291
+ const mayAutoRenderOutputStrings = programMayProduceOutputStrings(triples, frules, qrules);
292
+
293
+ if (streamMode && !hasQueries && !mayAutoRenderOutputStrings) {
291
294
  const usedInInput = prefixesUsedInInputTokens(toks, prefixes);
292
295
  const outPrefixes = restrictPrefixEnv(prefixes, usedInInput);
293
296
 
@@ -322,8 +325,6 @@ function main() {
322
325
  return;
323
326
  }
324
327
 
325
- const hasQueries = Array.isArray(qrules) && qrules.length;
326
-
327
328
  // Default (non-streaming):
328
329
  // - without log:query: derive everything first, then print only newly derived facts
329
330
  // - with log:query: derive everything first, then print only unique instantiated
@@ -345,6 +346,12 @@ function main() {
345
346
  outTriples = derived.map((df) => df.fact);
346
347
  }
347
348
 
349
+ const renderedOutputTriples = hasQueries ? outTriples : facts;
350
+ if (factsContainOutputStrings(renderedOutputTriples)) {
351
+ process.stdout.write(engine.collectOutputStringsFromFacts(renderedOutputTriples, prefixes));
352
+ return;
353
+ }
354
+
348
355
  const usedPrefixes = prefixes.prefixesUsedForOutput(outTriples);
349
356
 
350
357
  for (const [pfx, base] of usedPrefixes) {