eyeling 1.16.2 → 1.16.3

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/HANDBOOK.md CHANGED
@@ -484,6 +484,8 @@ When proving a goal with IRI predicate, Eyeling computes candidate facts by:
484
484
 
485
485
  This is a cheap selectivity heuristic. In type-heavy RDF, `(p,o)` is often extremely selective (e.g., `rdf:type` + a class IRI), so the PO index can be a major speed win.
486
486
 
487
+ The same selectivity idea is also reused by the single-premise forward-rule agenda in `forwardChain`: safe one-premise rules are pre-indexed by predicate / `(p,s)` / `(p,o)` patterns so a newly added fact only checks the small subset of rules that could match it.
488
+
487
489
  ### 7.3 Duplicate detection with fast keys
488
490
 
489
491
  When adding derived facts, Eyeling uses a fast-path duplicate check when possible:
@@ -662,6 +664,8 @@ until not changed
662
664
 
663
665
  Top-level input triples are kept as parsed (including non-ground triples such as ?X :p :o.). Groundness is enforced when adding derived facts during forward chaining, and when selecting printed/query output triples.
664
666
 
667
+ There is also a narrow fast path for some **single-premise** forward rules. When a rule has exactly one non-builtin premise and that premise cannot also be satisfied through backward rules, `forwardChain` can index the rule by that premise shape and fire it directly from newly added facts. This does **not** replace the general saturation loop; it is only an agenda-style shortcut for the safe one-premise case.
668
+
665
669
  ### 9.2 Strict-ground head optimization
666
670
 
667
671
  There is a nice micro-compiler optimization in `runFixpoint()`:
@@ -0,0 +1,106 @@
1
+ # =====================================================================
2
+ # Ershov mixed computation in Notation3
3
+ #
4
+ # This example illustrates the basic idea of Ershov mixed computation:
5
+ # a computation is split into two phases.
6
+ #
7
+ # Phase 1: specialization
8
+ # We take a generic pricing computation and the part of the input
9
+ # already known now (here: the customer is VIP), and we produce a
10
+ # residual program with those known values baked in.
11
+ #
12
+ # Phase 2: residual execution
13
+ # Later, when the remaining input becomes available
14
+ # (here: an order subtotal), we run the residual program and obtain
15
+ # the final result.
16
+ #
17
+ # In this example:
18
+ # generic formula: finalPrice = subtotal * discountRate + shippingFee
19
+ # known now: customerClass = VIP
20
+ # known later: subtotal = 100.00
21
+ #
22
+ # Specialization fixes:
23
+ # discountRate = 0.90
24
+ # shippingFee = 5.00
25
+ #
26
+ # So the residual program becomes:
27
+ # finalPrice = subtotal * 0.90 + 5.00
28
+ #
29
+ # With subtotal = 100.00, the expected result is:
30
+ # 100.00 * 0.90 + 5.00 = 95.00
31
+ #
32
+ # Typical eyeling output therefore includes:
33
+ # - the specialized residual rule
34
+ # - :futureOrder :computedByResidualProgram "95"^^xsd:decimal
35
+ #
36
+ # This is a tiny staging example, not a full partial evaluator.
37
+ # =====================================================================
38
+
39
+ @prefix : <http://example.org/mix#> .
40
+ @prefix log: <http://www.w3.org/2000/10/swap/log#> .
41
+ @prefix math:<http://www.w3.org/2000/10/swap/math#> .
42
+ @prefix xsd: <http://www.w3.org/2001/XMLSchema#> .
43
+
44
+ # ------------------------------------------------------------
45
+ # Generic computation, represented as static parameters
46
+ # ------------------------------------------------------------
47
+
48
+ :pricingProgram
49
+ :discountRate "0.90"^^xsd:decimal;
50
+ :shippingFee "5.00"^^xsd:decimal.
51
+
52
+ # Static input known at specialization time
53
+ :specialization :customerClass :VIP.
54
+
55
+ # ------------------------------------------------------------
56
+ # Phase 1: specialization
57
+ #
58
+ # Build a residual program for the VIP case by baking the static
59
+ # constants into a quoted rule.
60
+ # ------------------------------------------------------------
61
+
62
+ {
63
+ :pricingProgram :discountRate ?rate;
64
+ :shippingFee ?fee.
65
+ :specialization :customerClass :VIP.
66
+ }
67
+ =>
68
+ {
69
+ :specialization :residualProgram {
70
+ {
71
+ ?order :subtotal ?subtotal.
72
+ (?subtotal ?rate) math:product ?discounted.
73
+ (?discounted ?fee) math:sum ?final.
74
+ }
75
+ =>
76
+ {
77
+ ?order :finalPrice ?final.
78
+ } .
79
+ } .
80
+ } .
81
+
82
+ # ------------------------------------------------------------
83
+ # Phase 2: residual execution
84
+ #
85
+ # Later input arrives:
86
+ # :futureOrder :subtotal 100.00
87
+ #
88
+ # We combine that later input with the residual program, take the
89
+ # logical closure, and extract the inferred final price.
90
+ # ------------------------------------------------------------
91
+
92
+ {
93
+ :specialization :residualProgram ?rp.
94
+
95
+ ( ?rp
96
+ { :futureOrder :subtotal "100.00"^^xsd:decimal. }
97
+ ) log:conjunction ?run .
98
+
99
+ ?run log:conclusion ?closure .
100
+
101
+ ?closure log:includes { :futureOrder :finalPrice ?price. } .
102
+ }
103
+ =>
104
+ {
105
+ :futureOrder :computedByResidualProgram ?price.
106
+ } .
@@ -0,0 +1,15 @@
1
+ @prefix : <http://example.org/mix#> .
2
+ @prefix log: <http://www.w3.org/2000/10/swap/log#> .
3
+ @prefix math: <http://www.w3.org/2000/10/swap/math#> .
4
+ @prefix xsd: <http://www.w3.org/2001/XMLSchema#> .
5
+
6
+ :specialization :residualProgram {
7
+ {
8
+ ?order :subtotal ?subtotal .
9
+ (?subtotal "0.90"^^xsd:decimal) math:product ?discounted .
10
+ (?discounted "5.00"^^xsd:decimal) math:sum ?final .
11
+ } => {
12
+ ?order :finalPrice ?final .
13
+ } .
14
+ } .
15
+ :futureOrder :computedByResidualProgram "95"^^xsd:decimal .