eyeling 1.14.2 → 1.14.4
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 +1 -15
- package/examples/ackermann.n3 +2 -2
- package/examples/fastpow.n3 +111 -0
- package/examples/genetic-algorithm.n3 +163 -120
- package/examples/modexp.n3 +87 -0
- package/examples/output/fastpow.n3 +10 -0
- package/examples/output/genetic-algorithm.n3 +1 -1
- package/examples/output/modexp.n3 +8 -0
- package/eyeling-builtins.ttl +0 -5
- package/eyeling.js +19 -93
- package/lib/builtins.js +3 -90
- package/lib/cli.js +16 -3
- package/package.json +1 -1
package/HANDBOOK.md
CHANGED
|
@@ -979,15 +979,7 @@ If the types don’t fit any supported case, the builtin fails.
|
|
|
979
979
|
|
|
980
980
|
This is a pragmatic inversion, not a full algebra system.
|
|
981
981
|
|
|
982
|
-
|
|
983
|
-
|
|
984
|
-
**Shape:** `( $base $exp ) math:bigExponentiation $result`
|
|
985
|
-
|
|
986
|
-
- Exact integer exponentiation only.
|
|
987
|
-
- Requires integer `$base` and non-negative integer `$exp`.
|
|
988
|
-
- Fails if the estimated output size exceeds Eyeling’s built-in safety cap.
|
|
989
|
-
|
|
990
|
-
This builtin exists to avoid rule-level “repeat multiply” derivations that can explode memory for large exponents (e.g., the Ackermann example).
|
|
982
|
+
The **BigInt exact-integer mode** exists specifically to avoid rule-level “repeat multiply” derivations that can explode memory for large exponents (e.g., the Ackermann example).
|
|
991
983
|
|
|
992
984
|
#### Unary “math relations” (often invertible)
|
|
993
985
|
|
|
@@ -1563,12 +1555,6 @@ If `i` is out of range, `out` is the original string.
|
|
|
1563
1555
|
|
|
1564
1556
|
Returns the number of differing positions between `a` and `b`. Fails if the two strings have different lengths.
|
|
1565
1557
|
|
|
1566
|
-
#### `string:mutateSelectBest`
|
|
1567
|
-
|
|
1568
|
-
**Shape:** `( samples current target mutProb seedState ) string:mutateSelectBest ( best bestScore seedState2 )`
|
|
1569
|
-
|
|
1570
|
-
Generates `samples` mutated variants of `current` (mutating each character with probability `mutProb` percent), scores each candidate against `target` (Hamming distance), and returns the best candidate (lowest score). RNG is a deterministic 31-bit LCG, threaded via `seedState` → `seedState2`, so runs are reproducible.
|
|
1571
|
-
|
|
1572
1558
|
### Containment and prefix/suffix tests
|
|
1573
1559
|
|
|
1574
1560
|
- `string:contains`
|
package/examples/ackermann.n3
CHANGED
|
@@ -39,11 +39,11 @@
|
|
|
39
39
|
(?Y ?Z) math:product ?A.
|
|
40
40
|
}.
|
|
41
41
|
|
|
42
|
-
# exponentiation (x=3) — use BigInt exponentiation
|
|
42
|
+
# exponentiation (x=3) — use BigInt-capable math:exponentiation to avoid blow-up
|
|
43
43
|
{
|
|
44
44
|
(3 ?Y ?Z) :ackermann ?A.
|
|
45
45
|
} <= {
|
|
46
|
-
(?Z ?Y) math:
|
|
46
|
+
(?Z ?Y) math:exponentiation ?A.
|
|
47
47
|
}.
|
|
48
48
|
|
|
49
49
|
# exponentiation (x=3), tetration (x=4), pentation (x=5), hexation (x=6), etc
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
# ========================
|
|
2
|
+
# Fast exponentiation demo
|
|
3
|
+
# ========================
|
|
4
|
+
#
|
|
5
|
+
# Shows why using math:exponentiation (BigInt-capable) matters.
|
|
6
|
+
# The naive :powSlow definition uses repeated multiplication and should
|
|
7
|
+
# only be used for small exponents.
|
|
8
|
+
|
|
9
|
+
@prefix : <http://example.org/fastpow#>.
|
|
10
|
+
@prefix math: <http://www.w3.org/2000/10/swap/math#>.
|
|
11
|
+
@prefix log: <http://www.w3.org/2000/10/swap/log#>.
|
|
12
|
+
|
|
13
|
+
# ----------------------
|
|
14
|
+
# Fast power via builtin
|
|
15
|
+
# ----------------------
|
|
16
|
+
# pow(base, exp) = base^exp
|
|
17
|
+
{
|
|
18
|
+
(?B ?E) :pow ?R.
|
|
19
|
+
} <= {
|
|
20
|
+
(?B ?E) math:exponentiation ?R.
|
|
21
|
+
}.
|
|
22
|
+
|
|
23
|
+
# --------------------------------
|
|
24
|
+
# Slow power via repeated multiply
|
|
25
|
+
# --------------------------------
|
|
26
|
+
# powSlow(base, 0) = 1
|
|
27
|
+
{
|
|
28
|
+
(?B 0) :powSlow 1.
|
|
29
|
+
} <= {
|
|
30
|
+
0 math:equalTo 0.
|
|
31
|
+
}.
|
|
32
|
+
|
|
33
|
+
# powSlow(base, E>0) = powSlow(base, E-1) * base
|
|
34
|
+
{
|
|
35
|
+
(?B ?E) :powSlow ?R.
|
|
36
|
+
} <= {
|
|
37
|
+
?E math:greaterThan 0.
|
|
38
|
+
(?E 1) math:difference ?E1.
|
|
39
|
+
(?B ?E1) :powSlow ?Prev.
|
|
40
|
+
(?Prev ?B) math:product ?R.
|
|
41
|
+
}.
|
|
42
|
+
|
|
43
|
+
# ----------------------------------
|
|
44
|
+
# Power tower (tetration) using :pow
|
|
45
|
+
# ----------------------------------
|
|
46
|
+
# tower(base, 0) = 1
|
|
47
|
+
{
|
|
48
|
+
(?B 0) :tower 1.
|
|
49
|
+
} <= {
|
|
50
|
+
0 math:equalTo 0.
|
|
51
|
+
}.
|
|
52
|
+
|
|
53
|
+
# tower(base, H>0) = base ^ tower(base, H-1)
|
|
54
|
+
{
|
|
55
|
+
(?B ?H) :tower ?R.
|
|
56
|
+
} <= {
|
|
57
|
+
?H math:greaterThan 0.
|
|
58
|
+
(?H 1) math:difference ?H1.
|
|
59
|
+
(?B ?H1) :tower ?Prev.
|
|
60
|
+
(?B ?Prev) math:exponentiation ?R.
|
|
61
|
+
}.
|
|
62
|
+
|
|
63
|
+
# -----------------------------------------
|
|
64
|
+
# “Projection” helpers to keep output small
|
|
65
|
+
# -----------------------------------------
|
|
66
|
+
# powMod1e6(base, exp) = (base^exp) mod 1,000,000
|
|
67
|
+
{
|
|
68
|
+
(?B ?E) :powMod1e6 ?M.
|
|
69
|
+
} <= {
|
|
70
|
+
(?B ?E) :pow ?R.
|
|
71
|
+
(?R 1000000) math:remainder ?M.
|
|
72
|
+
}.
|
|
73
|
+
|
|
74
|
+
# towerMod1e6(base, height) = tower(base,height) mod 1,000,000
|
|
75
|
+
{
|
|
76
|
+
(?B ?H) :towerMod1e6 ?M.
|
|
77
|
+
} <= {
|
|
78
|
+
(?B ?H) :tower ?R.
|
|
79
|
+
(?R 1000000) math:remainder ?M.
|
|
80
|
+
}.
|
|
81
|
+
|
|
82
|
+
# ----
|
|
83
|
+
# test
|
|
84
|
+
# ----
|
|
85
|
+
{
|
|
86
|
+
# small sanity: fast and slow should agree
|
|
87
|
+
(2 10) :pow ?P10.
|
|
88
|
+
(2 10) :powSlow ?S10.
|
|
89
|
+
|
|
90
|
+
# big exponent, but only output mod 1e6 (so results stay short)
|
|
91
|
+
(2 10000) :powMod1e6 ?M1.
|
|
92
|
+
(3 10000) :powMod1e6 ?M2.
|
|
93
|
+
|
|
94
|
+
# power tower (2 ↑↑ 4 = 65536), and a slightly larger one modulo 1e6
|
|
95
|
+
(2 4) :tower ?T4.
|
|
96
|
+
(2 5) :towerMod1e6 ?TM5.
|
|
97
|
+
|
|
98
|
+
# WARNING: uncommenting this will be slow / memory-hungry (repeat multiply)
|
|
99
|
+
# (2 10000) :powSlow ?Boom.
|
|
100
|
+
}
|
|
101
|
+
=>
|
|
102
|
+
{
|
|
103
|
+
:test :is {
|
|
104
|
+
(2 10) :pow ?P10.
|
|
105
|
+
(2 10) :powSlow ?S10.
|
|
106
|
+
(2 10000) :powMod1e6 ?M1.
|
|
107
|
+
(3 10000) :powMod1e6 ?M2.
|
|
108
|
+
(2 4) :tower ?T4.
|
|
109
|
+
(2 5) :towerMod1e6 ?TM5.
|
|
110
|
+
}.
|
|
111
|
+
}.
|
|
@@ -1,19 +1,17 @@
|
|
|
1
1
|
# ==========================================================================================
|
|
2
2
|
# Genetic algorithm demo
|
|
3
3
|
#
|
|
4
|
-
#
|
|
5
|
-
# - Start with a random candidate string of the same length as the target.
|
|
6
|
-
# - Repeatedly create a batch of “children” by copying the current best string and randomly
|
|
7
|
-
# mutating each character with a small probability.
|
|
8
|
-
# - Score each child by how many positions differ from the target (Hamming distance).
|
|
9
|
-
# - Keep the best-scoring child as the new current string and iterate until the score is 0.
|
|
10
|
-
# This is a simple hill-climbing GA (selection + mutation, no crossover), using a seeded RNG
|
|
11
|
-
# so runs are reproducible.
|
|
4
|
+
# We "evolve" a genome (a bitstring) that encodes a target integer.
|
|
12
5
|
#
|
|
13
|
-
#
|
|
14
|
-
#
|
|
15
|
-
#
|
|
6
|
+
# - Genome: a string of '0'/'1' bits (same length as :weights).
|
|
7
|
+
# - Phenotype: sum of selected weights where the genome bit is '1'.
|
|
8
|
+
# - Fitness: remaining distance to the target, with a heavy penalty for overshoot:
|
|
9
|
+
# if sum <= target: fitness = target - sum
|
|
10
|
+
# if sum > target: fitness = 1_000_000 + (sum - target)
|
|
11
|
+
# - Variation: single-point mutation (flip one bit).
|
|
12
|
+
# - Selection: pick the candidate with the lowest fitness (ties keep the earlier candidate).
|
|
16
13
|
#
|
|
14
|
+
# With powers-of-two weights, this deterministic hill-climbing GA converges quickly.
|
|
17
15
|
# ==========================================================================================
|
|
18
16
|
|
|
19
17
|
@prefix : <urn:ga:>.
|
|
@@ -23,155 +21,200 @@
|
|
|
23
21
|
@prefix string: <http://www.w3.org/2000/10/swap/string#>.
|
|
24
22
|
|
|
25
23
|
:cfg
|
|
26
|
-
:
|
|
27
|
-
:
|
|
28
|
-
:seed 100;
|
|
24
|
+
:target 2026;
|
|
25
|
+
:maxGenerations 64;
|
|
29
26
|
|
|
30
|
-
#
|
|
31
|
-
|
|
32
|
-
|
|
27
|
+
# weights align with bit positions (index 0 is the left-most bit):
|
|
28
|
+
# genome = b0 b1 ... b10
|
|
29
|
+
# value = b0*1024 + b1*512 + ... + b10*1
|
|
30
|
+
:weights (1024 512 256 128 64 32 16 8 4 2 1).
|
|
33
31
|
|
|
34
|
-
|
|
35
|
-
|
|
32
|
+
# -------------
|
|
33
|
+
# small helpers
|
|
34
|
+
# -------------
|
|
36
35
|
|
|
37
|
-
# ------------------------
|
|
38
|
-
# Small arithmetic helpers
|
|
39
|
-
# ------------------------
|
|
40
|
-
|
|
41
|
-
{ ( ?N 1 ) :dec ?N1 } <= { ( ?N 1 ) math:difference ?N1 }.
|
|
42
36
|
{ ( ?N 1 ) :inc ?N1 } <= { ( ?N 1 ) math:sum ?N1 }.
|
|
43
37
|
|
|
44
|
-
#
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
38
|
+
# build a string of N zeros
|
|
39
|
+
{ ( 0 ) :zeros "" } <= true.
|
|
40
|
+
|
|
41
|
+
{ ( ?N ) :zeros ?S } <= {
|
|
42
|
+
?N math:greaterThan 0 .
|
|
43
|
+
( ?N 1 ) math:difference ?N1 .
|
|
44
|
+
( ?N1 ) :zeros ?Rest .
|
|
45
|
+
( "%s%s" "0" ?Rest ) string:format ?S
|
|
46
|
+
}.
|
|
47
|
+
|
|
48
|
+
# flip a bit at index i in a 0/1 string
|
|
49
|
+
{ ( ?S ?I ) :flipBit ?Out } <= {
|
|
50
|
+
( ?S ?I ) string:charAt "0" .
|
|
51
|
+
( ?S ?I "1" ) string:setCharAt ?Out
|
|
52
|
+
}.
|
|
53
|
+
|
|
54
|
+
{ ( ?S ?I ) :flipBit ?Out } <= {
|
|
55
|
+
( ?S ?I ) string:charAt "1" .
|
|
56
|
+
( ?S ?I "0" ) string:setCharAt ?Out
|
|
57
|
+
}.
|
|
58
|
+
|
|
59
|
+
# generate all single-bit mutants of S: [flip(0), flip(1), ..., flip(len-1)]
|
|
60
|
+
{ ( ?S ?Len ) :mutants ?Out } <= {
|
|
61
|
+
( ?S 0 ?Len ) :mutantsFrom ?Out
|
|
62
|
+
}.
|
|
63
|
+
|
|
64
|
+
{ ( ?S ?I ?Len ) :mutantsFrom () } <= {
|
|
65
|
+
?I math:equalTo ?Len
|
|
66
|
+
}.
|
|
67
|
+
|
|
68
|
+
{ ( ?S ?I ?Len ) :mutantsFrom ?Out } <= {
|
|
69
|
+
?I math:lessThan ?Len .
|
|
70
|
+
( ?S ?I ) :flipBit ?Cand .
|
|
71
|
+
( ?I 1 ) :inc ?I1 .
|
|
72
|
+
( ?S ?I1 ?Len ) :mutantsFrom ?Rest .
|
|
73
|
+
( ( ?Cand ) ?Rest ) list:append ?Out
|
|
74
|
+
}.
|
|
75
|
+
|
|
76
|
+
# ------------------------
|
|
77
|
+
# decode genome -> integer
|
|
78
|
+
# ------------------------
|
|
48
79
|
|
|
49
|
-
{ ?
|
|
50
|
-
|
|
51
|
-
( ?
|
|
52
|
-
( ?T 2147483648 ) math:remainder ?S1
|
|
80
|
+
{ ( ?Bits ?Weights ) :value ?Sum } <= {
|
|
81
|
+
?Bits string:length ?Len .
|
|
82
|
+
( ?Bits ?Weights 0 ?Len 0 ) :valueAcc ?Sum
|
|
53
83
|
}.
|
|
54
84
|
|
|
55
|
-
{ ( ?
|
|
56
|
-
?
|
|
57
|
-
( ?S1 ?N ) math:product ?A .
|
|
58
|
-
( ?A ?A ) math:sum ?TwoA .
|
|
59
|
-
( ?TwoA 2147483648 ) math:sum ?Num .
|
|
60
|
-
( 2147483648 2 ) math:product ?Den .
|
|
61
|
-
( ?Num ?Den ) math:integerQuotient ?R
|
|
85
|
+
{ ( ?Bits ?Weights ?I ?Len ?Acc ) :valueAcc ?Acc } <= {
|
|
86
|
+
?I math:equalTo ?Len
|
|
62
87
|
}.
|
|
63
88
|
|
|
64
|
-
{ ?
|
|
65
|
-
|
|
66
|
-
( ?
|
|
67
|
-
|
|
89
|
+
{ ( ?Bits ?Weights ?I ?Len ?Acc ) :valueAcc ?Sum } <= {
|
|
90
|
+
?I math:lessThan ?Len .
|
|
91
|
+
( ?Weights ?I ) list:memberAt ?W .
|
|
92
|
+
|
|
93
|
+
( ?Bits ?I ) string:charAt "1" .
|
|
94
|
+
( ?Acc ?W ) math:sum ?Acc1 .
|
|
95
|
+
( ?I 1 ) :inc ?I1 .
|
|
96
|
+
( ?Bits ?Weights ?I1 ?Len ?Acc1 ) :valueAcc ?Sum
|
|
68
97
|
}.
|
|
69
98
|
|
|
70
|
-
{ (
|
|
99
|
+
{ ( ?Bits ?Weights ?I ?Len ?Acc ) :valueAcc ?Sum } <= {
|
|
100
|
+
?I math:lessThan ?Len .
|
|
101
|
+
( ?Weights ?I ) list:memberAt ?W .
|
|
71
102
|
|
|
72
|
-
|
|
73
|
-
?
|
|
74
|
-
( ?Len
|
|
75
|
-
?S0 :randomAlpha ( ?Ch ?S1 ) .
|
|
76
|
-
( ?Len1 ?S1 ) :randomText ( ?Rest ?S2 ) .
|
|
77
|
-
( "%s%s" ?Ch ?Rest ) string:format ?Out
|
|
103
|
+
( ?Bits ?I ) string:charAt "0" .
|
|
104
|
+
( ?I 1 ) :inc ?I1 .
|
|
105
|
+
( ?Bits ?Weights ?I1 ?Len ?Acc ) :valueAcc ?Sum
|
|
78
106
|
}.
|
|
79
107
|
|
|
80
108
|
# -------------------------
|
|
81
|
-
#
|
|
109
|
+
# fitness (lower is better)
|
|
82
110
|
# -------------------------
|
|
83
111
|
|
|
84
|
-
{ (
|
|
112
|
+
{ ( ?Sum ?Target ) :fitness ?F } <= {
|
|
113
|
+
?Sum math:notGreaterThan ?Target .
|
|
114
|
+
( ?Target ?Sum ) math:difference ?F
|
|
115
|
+
}.
|
|
116
|
+
|
|
117
|
+
{ ( ?Sum ?Target ) :fitness ?F } <= {
|
|
118
|
+
?Sum math:greaterThan ?Target .
|
|
119
|
+
( ?Sum ?Target ) math:difference ?Over .
|
|
120
|
+
( 1000000 ?Over ) math:sum ?F
|
|
121
|
+
}.
|
|
122
|
+
|
|
123
|
+
{ ( ?Bits ?Target ?Weights ) :candidateScore ( ?Fit ?Sum ) } <= {
|
|
124
|
+
( ?Bits ?Weights ) :value ?Sum .
|
|
125
|
+
( ?Sum ?Target ) :fitness ?Fit
|
|
126
|
+
}.
|
|
127
|
+
|
|
128
|
+
# pick best of two candidates by fitness (ties keep the left candidate)
|
|
129
|
+
{ ( ?C1 ?S1 ?Sum1 ?C2 ?S2 ?Sum2 ) :pickBest ( ?C1 ?S1 ?Sum1 ) } <= {
|
|
130
|
+
?S1 math:notGreaterThan ?S2
|
|
131
|
+
}.
|
|
132
|
+
|
|
133
|
+
{ ( ?C1 ?S1 ?Sum1 ?C2 ?S2 ?Sum2 ) :pickBest ( ?C2 ?S2 ?Sum2 ) } <= {
|
|
134
|
+
?S1 math:greaterThan ?S2
|
|
135
|
+
}.
|
|
136
|
+
|
|
137
|
+
# best candidate from a list
|
|
138
|
+
{ ( ?Target ?Weights ?L ) :bestMutant ( ?Best ?BestScore ?BestSum ) } <= {
|
|
139
|
+
?L list:length 1 .
|
|
140
|
+
?L list:first ?Best .
|
|
141
|
+
( ?Best ?Target ?Weights ) :candidateScore ( ?BestScore ?BestSum )
|
|
142
|
+
}.
|
|
143
|
+
|
|
144
|
+
{ ( ?Target ?Weights ?L ) :bestMutant ( ?Best ?BestScore ?BestSum ) } <= {
|
|
145
|
+
?L list:length ?N .
|
|
146
|
+
?N math:greaterThan 1 .
|
|
147
|
+
|
|
148
|
+
?L list:first ?H .
|
|
149
|
+
?L list:rest ?T .
|
|
150
|
+
|
|
151
|
+
( ?Target ?Weights ?T ) :bestMutant ( ?B2 ?S2 ?Sum2 ) .
|
|
152
|
+
( ?H ?Target ?Weights ) :candidateScore ( ?S1 ?Sum1 ) .
|
|
85
153
|
|
|
86
|
-
|
|
87
|
-
?Every math:greaterThan 0 .
|
|
88
|
-
( ?Gen ?Every ) math:remainder ?R .
|
|
89
|
-
?R math:equalTo 0 .
|
|
90
|
-
?Gen log:trace ( ?Score ?Value )
|
|
154
|
+
( ?H ?S1 ?Sum1 ?B2 ?S2 ?Sum2 ) :pickBest ( ?Best ?BestScore ?BestSum )
|
|
91
155
|
}.
|
|
92
156
|
|
|
93
157
|
# --------------
|
|
94
158
|
# evolution loop
|
|
95
159
|
# --------------
|
|
96
160
|
|
|
97
|
-
#
|
|
98
|
-
{ ( ?
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
# Stop when generation cap is reached (only if MaxGen > 0)
|
|
102
|
-
{ ( ?Current ?Score ?Target ?MutProb ?Samples ?Gen ?S0 ?MaxGen ?TraceEvery )
|
|
103
|
-
:evolve ( ?Current ?Gen ?S0 ) } <= {
|
|
104
|
-
?Score math:notEqualTo 0 .
|
|
105
|
-
?MaxGen math:greaterThan 0 .
|
|
106
|
-
?Gen math:equalTo ?MaxGen
|
|
161
|
+
# solved
|
|
162
|
+
{ ( ?Bits ?Target ?Weights ?Gen ?MaxGen ) :evolve ( ?Bits ?Gen ) } <= {
|
|
163
|
+
( ?Bits ?Target ?Weights ) :candidateScore ( 0 ?Sum )
|
|
107
164
|
}.
|
|
108
165
|
|
|
109
|
-
#
|
|
110
|
-
{ ( ?
|
|
111
|
-
|
|
112
|
-
?Score math:notEqualTo 0 .
|
|
113
|
-
( ?Samples ?Current ?Target ?MutProb ?S0 )
|
|
114
|
-
string:mutateSelectBest
|
|
115
|
-
( ?Best ?BestScore ?S1 ) .
|
|
116
|
-
( ?Gen 1 ) :inc ?Gen1 .
|
|
117
|
-
( ?TraceEvery ?Gen1 ?BestScore ?Best ) :traceMaybe true .
|
|
118
|
-
( ?Best ?BestScore ?Target ?MutProb ?Samples ?Gen1 ?S1 0 ?TraceEvery )
|
|
119
|
-
:evolve ( ?Final ?FinalGen ?S2 )
|
|
166
|
+
# generation cap (safety)
|
|
167
|
+
{ ( ?Bits ?Target ?Weights ?Gen ?MaxGen ) :evolve ( ?Bits ?Gen ) } <= {
|
|
168
|
+
?Gen math:equalTo ?MaxGen
|
|
120
169
|
}.
|
|
121
170
|
|
|
122
|
-
#
|
|
123
|
-
{ ( ?
|
|
124
|
-
:evolve ( ?Final ?FinalGen ?S2 ) } <= {
|
|
125
|
-
?Score math:notEqualTo 0 .
|
|
126
|
-
?MaxGen math:greaterThan 0 .
|
|
171
|
+
# stop if best doesn't improve
|
|
172
|
+
{ ( ?Bits ?Target ?Weights ?Gen ?MaxGen ) :evolve ( ?Bits ?Gen ) } <= {
|
|
127
173
|
?Gen math:lessThan ?MaxGen .
|
|
128
|
-
( ?
|
|
129
|
-
string:mutateSelectBest
|
|
130
|
-
( ?Best ?BestScore ?S1 ) .
|
|
131
|
-
( ?Gen 1 ) :inc ?Gen1 .
|
|
132
|
-
( ?TraceEvery ?Gen1 ?BestScore ?Best ) :traceMaybe true .
|
|
133
|
-
( ?Best ?BestScore ?Target ?MutProb ?Samples ?Gen1 ?S1 ?MaxGen ?TraceEvery )
|
|
134
|
-
:evolve ( ?Final ?FinalGen ?S2 )
|
|
135
|
-
}.
|
|
174
|
+
( ?Bits ?Target ?Weights ) :candidateScore ( ?Score ?Sum ) .
|
|
136
175
|
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
176
|
+
?Bits string:length ?Len .
|
|
177
|
+
( ?Bits ?Len ) :mutants ?Ms .
|
|
178
|
+
( ( ?Bits ) ?Ms ) list:append ?Candidates .
|
|
140
179
|
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
:seed ?Seed;
|
|
145
|
-
:traceEvery ?TraceEvery;
|
|
146
|
-
:maxGenerations ?MaxGen.
|
|
147
|
-
|
|
148
|
-
?TargetString string:length ?Len .
|
|
180
|
+
( ?Target ?Weights ?Candidates ) :bestMutant ( ?Best ?BestScore ?BestSum ) .
|
|
181
|
+
?BestScore math:equalTo ?Score
|
|
182
|
+
}.
|
|
149
183
|
|
|
150
|
-
|
|
184
|
+
# keep evolving while improvement exists
|
|
185
|
+
{ ( ?Bits ?Target ?Weights ?Gen ?MaxGen ) :evolve ( ?Final ?FinalGen ) } <= {
|
|
186
|
+
?Gen math:lessThan ?MaxGen .
|
|
187
|
+
( ?Bits ?Target ?Weights ) :candidateScore ( ?Score ?Sum ) .
|
|
151
188
|
|
|
152
|
-
|
|
153
|
-
( ?
|
|
189
|
+
?Bits string:length ?Len .
|
|
190
|
+
( ?Bits ?Len ) :mutants ?Ms .
|
|
191
|
+
( ( ?Bits ) ?Ms ) list:append ?Candidates .
|
|
154
192
|
|
|
155
|
-
( ?
|
|
156
|
-
|
|
157
|
-
( ?Value ?Gen ?S2 ) .
|
|
193
|
+
( ?Target ?Weights ?Candidates ) :bestMutant ( ?Best ?BestScore ?BestSum ) .
|
|
194
|
+
?BestScore math:notEqualTo ?Score .
|
|
158
195
|
|
|
159
|
-
|
|
160
|
-
( ?
|
|
161
|
-
?Value log:equalTo ?TargetString .
|
|
162
|
-
?S2 log:equalTo ?_FinalSeedState
|
|
196
|
+
( ?Gen 1 ) :inc ?Gen1 .
|
|
197
|
+
( ?Best ?Target ?Weights ?Gen1 ?MaxGen ) :evolve ( ?Final ?FinalGen )
|
|
163
198
|
}.
|
|
164
199
|
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
200
|
+
# --------------
|
|
201
|
+
# query / output
|
|
202
|
+
# --------------
|
|
203
|
+
|
|
204
|
+
{
|
|
205
|
+
:cfg :target ?T;
|
|
206
|
+
:maxGenerations ?Max;
|
|
207
|
+
:weights ?W.
|
|
208
|
+
|
|
209
|
+
?W list:length ?Len .
|
|
210
|
+
( ?Len ) :zeros ?Start .
|
|
168
211
|
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
212
|
+
( ?Start ?T ?W 0 ?Max ) :evolve ( ?Best ?Gen ) .
|
|
213
|
+
( ?Best ?W ) :value ?Sum .
|
|
214
|
+
?Sum math:equalTo ?T .
|
|
172
215
|
|
|
173
|
-
|
|
174
|
-
|
|
216
|
+
( "GA evolved %s -> %s in %s generations.\n" ?Best ?Sum ?Gen )
|
|
217
|
+
string:format ?Line
|
|
175
218
|
}
|
|
176
219
|
log:query
|
|
177
220
|
{ 1 log:outputString ?Line }.
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
# ===============================================
|
|
2
|
+
# Fast modular exponentiation (repeated squaring)
|
|
3
|
+
# ===============================================
|
|
4
|
+
|
|
5
|
+
@prefix math: <http://www.w3.org/2000/10/swap/math#>.
|
|
6
|
+
@prefix : <https://eyereasoner.github.io/ns#>.
|
|
7
|
+
|
|
8
|
+
# (a * b) mod m
|
|
9
|
+
{
|
|
10
|
+
(?A ?B ?M) :modMul ?R.
|
|
11
|
+
} <= {
|
|
12
|
+
(?A ?B) math:product ?P.
|
|
13
|
+
(?P ?M) math:remainder ?R.
|
|
14
|
+
}.
|
|
15
|
+
|
|
16
|
+
# modPow(b, 0, m) = 1 mod m
|
|
17
|
+
{
|
|
18
|
+
(?B 0 ?M) :modPow ?R.
|
|
19
|
+
} <= {
|
|
20
|
+
?M math:greaterThan 0.
|
|
21
|
+
(1 ?M) math:remainder ?R.
|
|
22
|
+
}.
|
|
23
|
+
|
|
24
|
+
# modPow(b, 1, m) = b mod m
|
|
25
|
+
{
|
|
26
|
+
(?B 1 ?M) :modPow ?R.
|
|
27
|
+
} <= {
|
|
28
|
+
?M math:greaterThan 0.
|
|
29
|
+
(?B ?M) math:remainder ?R.
|
|
30
|
+
}.
|
|
31
|
+
|
|
32
|
+
# even exponent: modPow(b, e, m) = modPow((b*b mod m), e/2, m)
|
|
33
|
+
{
|
|
34
|
+
(?B ?E ?M) :modPow ?R.
|
|
35
|
+
} <= {
|
|
36
|
+
?M math:greaterThan 0.
|
|
37
|
+
?E math:greaterThan 1.
|
|
38
|
+
(?E 2) math:remainder 0.
|
|
39
|
+
|
|
40
|
+
(?B ?B ?M) :modMul ?B2.
|
|
41
|
+
(?E 2) math:integerQuotient ?Half.
|
|
42
|
+
(?B2 ?Half ?M) :modPow ?R.
|
|
43
|
+
}.
|
|
44
|
+
|
|
45
|
+
# odd exponent: modPow(b, e, m) = (b * modPow((b*b mod m), (e-1)/2, m)) mod m
|
|
46
|
+
{
|
|
47
|
+
(?B ?E ?M) :modPow ?R.
|
|
48
|
+
} <= {
|
|
49
|
+
?M math:greaterThan 0.
|
|
50
|
+
?E math:greaterThan 1.
|
|
51
|
+
(?E 2) math:remainder 1.
|
|
52
|
+
|
|
53
|
+
(?B ?B ?M) :modMul ?B2.
|
|
54
|
+
(?E 1) math:difference ?E1.
|
|
55
|
+
(?E1 2) math:integerQuotient ?Half.
|
|
56
|
+
|
|
57
|
+
(?B2 ?Half ?M) :modPow ?T.
|
|
58
|
+
(?B ?T ?M) :modMul ?R.
|
|
59
|
+
}.
|
|
60
|
+
|
|
61
|
+
# -----------------
|
|
62
|
+
# tests / showcases
|
|
63
|
+
# -----------------
|
|
64
|
+
{
|
|
65
|
+
# sanity check against a small naive computation:
|
|
66
|
+
(7 13) math:exponentiation ?PowSmall.
|
|
67
|
+
(?PowSmall 97) math:remainder ?NaiveSmall.
|
|
68
|
+
(7 13 97) :modPow ?FastSmall.
|
|
69
|
+
|
|
70
|
+
# “impressive” case: 7^1,000,000,000 mod 1,000,000,007
|
|
71
|
+
(7 1000000000 1000000007) :modPow ?R1.
|
|
72
|
+
|
|
73
|
+
# exponent itself computed via exponentiation: 2^25 = 33,554,432
|
|
74
|
+
(2 25) math:exponentiation ?E25.
|
|
75
|
+
(3 ?E25 1000000007) :modPow ?R2.
|
|
76
|
+
|
|
77
|
+
# last 12 digits of 2^(2^20)
|
|
78
|
+
(2 20) math:exponentiation ?E20.
|
|
79
|
+
(2 ?E20 1000000000000) :modPow ?Last12.
|
|
80
|
+
}
|
|
81
|
+
=>
|
|
82
|
+
{
|
|
83
|
+
:test :smallCheck [ :naive ?NaiveSmall; :fast ?FastSmall ].
|
|
84
|
+
:test :sevenPow1e9Mod1e9p7 ?R1.
|
|
85
|
+
:test :threePow2Pow25Mod1e9p7 ?R2.
|
|
86
|
+
:test :last12DigitsOf2Pow2Pow20 ?Last12.
|
|
87
|
+
}.
|
package/eyeling-builtins.ttl
CHANGED
|
@@ -101,9 +101,6 @@ math:rounded a ex:Builtin ; ex:kind ex:Function ;
|
|
|
101
101
|
math:exponentiation a ex:Builtin ; ex:kind ex:Function ;
|
|
102
102
|
rdfs:comment "Exponentiation. Forward: (base exponent) -> result. If both arguments are integer literals and exponent is non-negative, Eyeling uses exact BigInt exponentiation (with a safety cap on result size). Otherwise it falls back to Number exponentiation. Limited inverse: if base is numeric and exponent is a variable, may solve exponent via logs for positive base != 1 and positive result (Number mode only)." .
|
|
103
103
|
|
|
104
|
-
math:bigExponentiation a ex:Builtin ; ex:kind ex:Function ;
|
|
105
|
-
rdfs:comment "Exact integer exponentiation (BigInt-only). Shape: (base exponent) math:bigExponentiation result. Requires integer base and non-negative integer exponent; fails if the estimated result size exceeds Eyeling's safety cap." .
|
|
106
|
-
|
|
107
104
|
math:absoluteValue a ex:Builtin ; ex:kind ex:Function ;
|
|
108
105
|
rdfs:comment "Absolute value. Computes |s| and unifies/binds object; output datatype follows common numeric datatype selection." .
|
|
109
106
|
|
|
@@ -349,5 +346,3 @@ string:setCharAt a ex:Builtin ; ex:kind ex:Function ;
|
|
|
349
346
|
string:hammingDistance a ex:Builtin ; ex:kind ex:Function ;
|
|
350
347
|
rdfs:comment "Function: subject is a 2-item list (a b). Binds/unifies object with the number of differing positions (Hamming distance). Fails if lengths differ." .
|
|
351
348
|
|
|
352
|
-
string:mutateSelectBest a ex:Builtin ; ex:kind ex:Function ;
|
|
353
|
-
rdfs:comment "Shape: (samples current target mutProb seedState) string:mutateSelectBest (best bestScore seedState2). Generates samples mutated variants of current (mutating each character with probability mutProb percent), scores each candidate against target (Hamming distance), and returns the best candidate (lowest score). RNG is a deterministic 31-bit LCG, threaded via seedState → seedState2, so runs are reproducible." .
|
package/eyeling.js
CHANGED
|
@@ -1792,10 +1792,9 @@ function evalBuiltin(goal, subst, facts, backRules, depth, varGen, maxResults) {
|
|
|
1792
1792
|
}
|
|
1793
1793
|
|
|
1794
1794
|
// math:exponentiation
|
|
1795
|
-
//
|
|
1796
|
-
|
|
1797
|
-
|
|
1798
|
-
|
|
1795
|
+
// Schema: ( $base $exp ) math:exponentiation $result
|
|
1796
|
+
// Supports exact integer exponentiation via BigInt when both inputs are integers and exp >= 0.
|
|
1797
|
+
if (pv === MATH_NS + 'exponentiation') {
|
|
1799
1798
|
if (!(g.s instanceof ListTerm) || g.s.elems.length !== 2) return [];
|
|
1800
1799
|
const baseTerm = g.s.elems[0];
|
|
1801
1800
|
const expTerm = g.s.elems[1];
|
|
@@ -1832,9 +1831,6 @@ function evalBuiltin(goal, subst, facts, backRules, depth, varGen, maxResults) {
|
|
|
1832
1831
|
return s2 !== null ? [s2] : [];
|
|
1833
1832
|
}
|
|
1834
1833
|
|
|
1835
|
-
// bigExponentiation is intentionally strict.
|
|
1836
|
-
if (onlyBigInt) return [];
|
|
1837
|
-
|
|
1838
1834
|
// 2) Numeric mode (Number): forward + limited inverse
|
|
1839
1835
|
const a = parseNum(baseTerm);
|
|
1840
1836
|
const b = a !== null ? parseNum(expTerm) : null;
|
|
@@ -3614,89 +3610,6 @@ function evalBuiltin(goal, subst, facts, backRules, depth, varGen, maxResults) {
|
|
|
3614
3610
|
return s2 !== null ? [s2] : [];
|
|
3615
3611
|
}
|
|
3616
3612
|
|
|
3617
|
-
// string:mutateSelectBest
|
|
3618
|
-
// Schema:
|
|
3619
|
-
// ( $samples $current $target $mutProb $seedState )
|
|
3620
|
-
// string:mutateSelectBest
|
|
3621
|
-
// ( $best $bestScore $seedState2 )
|
|
3622
|
-
//
|
|
3623
|
-
// Deterministic 31-bit LCG (same as the GA demo):
|
|
3624
|
-
// state = (1103515245 * state + 12345) % 2^31
|
|
3625
|
-
// and randRound(N) = Math.round((state/2^31) * N) with state advanced once per draw.
|
|
3626
|
-
if (pv === STRING_NS + 'mutateSelectBest') {
|
|
3627
|
-
if (!(g.s instanceof ListTerm) || g.s.elems.length !== 5) return [];
|
|
3628
|
-
|
|
3629
|
-
const samplesNum = parseNum(g.s.elems[0]);
|
|
3630
|
-
const current = termToJsXsdStringNoLang(g.s.elems[1]);
|
|
3631
|
-
const target = termToJsXsdStringNoLang(g.s.elems[2]);
|
|
3632
|
-
const mutProbNum = parseNum(g.s.elems[3]);
|
|
3633
|
-
const seedNum = parseNum(g.s.elems[4]);
|
|
3634
|
-
|
|
3635
|
-
if (samplesNum === null || current === null || target === null || mutProbNum === null || seedNum === null)
|
|
3636
|
-
return [];
|
|
3637
|
-
if (current.length !== target.length) return [];
|
|
3638
|
-
|
|
3639
|
-
const samples = Math.max(1, Math.trunc(samplesNum));
|
|
3640
|
-
const mutProb = Math.max(0, Math.trunc(mutProbNum));
|
|
3641
|
-
const seed0 = Math.trunc(seedNum);
|
|
3642
|
-
|
|
3643
|
-
let state = BigInt(seed0);
|
|
3644
|
-
const MOD = 2147483648n; // 2^31
|
|
3645
|
-
const A = 1103515245n;
|
|
3646
|
-
const C = 12345n;
|
|
3647
|
-
|
|
3648
|
-
function rnd() {
|
|
3649
|
-
state = (A * state + C) % MOD;
|
|
3650
|
-
return Number(state) / 2147483648;
|
|
3651
|
-
}
|
|
3652
|
-
|
|
3653
|
-
function randRound(N) {
|
|
3654
|
-
return Math.round(rnd() * N);
|
|
3655
|
-
}
|
|
3656
|
-
|
|
3657
|
-
function randomAlpha() {
|
|
3658
|
-
const p = randRound(26);
|
|
3659
|
-
return p === 0 ? ' ' : String.fromCharCode(64 + p);
|
|
3660
|
-
}
|
|
3661
|
-
|
|
3662
|
-
function mutate(str) {
|
|
3663
|
-
let out = '';
|
|
3664
|
-
for (let i = 0; i < str.length; i++) {
|
|
3665
|
-
const p = randRound(100);
|
|
3666
|
-
if (p > mutProb) out += str[i];
|
|
3667
|
-
else out += randomAlpha();
|
|
3668
|
-
}
|
|
3669
|
-
return out;
|
|
3670
|
-
}
|
|
3671
|
-
|
|
3672
|
-
function score(str) {
|
|
3673
|
-
let diffs = 0;
|
|
3674
|
-
for (let i = 0; i < target.length; i++) if (str[i] !== target[i]) diffs++;
|
|
3675
|
-
return diffs;
|
|
3676
|
-
}
|
|
3677
|
-
|
|
3678
|
-
let best = '';
|
|
3679
|
-
let bestScore = Infinity;
|
|
3680
|
-
|
|
3681
|
-
for (let i = 0; i < samples; i++) {
|
|
3682
|
-
const cand = mutate(current);
|
|
3683
|
-
const candScore = score(cand);
|
|
3684
|
-
if (candScore < bestScore) {
|
|
3685
|
-
best = cand;
|
|
3686
|
-
bestScore = candScore;
|
|
3687
|
-
}
|
|
3688
|
-
}
|
|
3689
|
-
|
|
3690
|
-
const outList = new ListTerm([
|
|
3691
|
-
makeStringLiteral(best),
|
|
3692
|
-
internLiteral(String(bestScore)),
|
|
3693
|
-
internLiteral(state.toString()),
|
|
3694
|
-
]);
|
|
3695
|
-
|
|
3696
|
-
const s2 = unifyTerm(g.o, outList, subst);
|
|
3697
|
-
return s2 !== null ? [s2] : [];
|
|
3698
|
-
}
|
|
3699
|
-
|
|
3700
3613
|
// Unknown builtin
|
|
3701
3614
|
return [];
|
|
3702
3615
|
}
|
|
@@ -3966,7 +3879,7 @@ function main() {
|
|
|
3966
3879
|
` -e, --enforce-https Rewrite http:// IRIs to https:// for log dereferencing builtins.\n` +
|
|
3967
3880
|
` -h, --help Show this help and exit.\n` +
|
|
3968
3881
|
` -p, --proof-comments Enable proof explanations.\n` +
|
|
3969
|
-
` -r, --strings Print log:outputString strings (ordered by key)
|
|
3882
|
+
` -r, --strings Print log:outputString strings (ordered by key), including via log:query.\n` +
|
|
3970
3883
|
` -s, --super-restricted Disable all builtins except => and <=.\n` +
|
|
3971
3884
|
` -t, --stream Stream derived triples as soon as they are derived.\n` +
|
|
3972
3885
|
` -v, --version Print version and exit.\n`;
|
|
@@ -4076,8 +3989,21 @@ function main() {
|
|
|
4076
3989
|
// If requested, print log:outputString values (ordered by subject key) and exit.
|
|
4077
3990
|
// Note: log:outputString values may depend on derived facts, so we must saturate first.
|
|
4078
3991
|
if (outputStringsMode) {
|
|
4079
|
-
|
|
4080
|
-
|
|
3992
|
+
const hasQueries = Array.isArray(qrules) && qrules.length;
|
|
3993
|
+
|
|
3994
|
+
// If log:query directives are present, the intended output may not be part of the
|
|
3995
|
+
// saturated fact store (queries are output-selection statements). In that case,
|
|
3996
|
+
// collect log:outputString triples from the instantiated query conclusions.
|
|
3997
|
+
let outTriples;
|
|
3998
|
+
if (hasQueries) {
|
|
3999
|
+
const res = engine.forwardChainAndCollectLogQueryConclusions(facts, frules, brules, qrules);
|
|
4000
|
+
outTriples = res.queryTriples;
|
|
4001
|
+
} else {
|
|
4002
|
+
engine.forwardChain(facts, frules, brules);
|
|
4003
|
+
outTriples = facts;
|
|
4004
|
+
}
|
|
4005
|
+
|
|
4006
|
+
const out = engine.collectOutputStringsFromFacts(outTriples, prefixes);
|
|
4081
4007
|
if (out) process.stdout.write(out);
|
|
4082
4008
|
process.exit(0);
|
|
4083
4009
|
}
|
package/lib/builtins.js
CHANGED
|
@@ -1780,10 +1780,9 @@ function evalBuiltin(goal, subst, facts, backRules, depth, varGen, maxResults) {
|
|
|
1780
1780
|
}
|
|
1781
1781
|
|
|
1782
1782
|
// math:exponentiation
|
|
1783
|
-
//
|
|
1784
|
-
|
|
1785
|
-
|
|
1786
|
-
|
|
1783
|
+
// Schema: ( $base $exp ) math:exponentiation $result
|
|
1784
|
+
// Supports exact integer exponentiation via BigInt when both inputs are integers and exp >= 0.
|
|
1785
|
+
if (pv === MATH_NS + 'exponentiation') {
|
|
1787
1786
|
if (!(g.s instanceof ListTerm) || g.s.elems.length !== 2) return [];
|
|
1788
1787
|
const baseTerm = g.s.elems[0];
|
|
1789
1788
|
const expTerm = g.s.elems[1];
|
|
@@ -1820,9 +1819,6 @@ function evalBuiltin(goal, subst, facts, backRules, depth, varGen, maxResults) {
|
|
|
1820
1819
|
return s2 !== null ? [s2] : [];
|
|
1821
1820
|
}
|
|
1822
1821
|
|
|
1823
|
-
// bigExponentiation is intentionally strict.
|
|
1824
|
-
if (onlyBigInt) return [];
|
|
1825
|
-
|
|
1826
1822
|
// 2) Numeric mode (Number): forward + limited inverse
|
|
1827
1823
|
const a = parseNum(baseTerm);
|
|
1828
1824
|
const b = a !== null ? parseNum(expTerm) : null;
|
|
@@ -3602,89 +3598,6 @@ function evalBuiltin(goal, subst, facts, backRules, depth, varGen, maxResults) {
|
|
|
3602
3598
|
return s2 !== null ? [s2] : [];
|
|
3603
3599
|
}
|
|
3604
3600
|
|
|
3605
|
-
// string:mutateSelectBest
|
|
3606
|
-
// Schema:
|
|
3607
|
-
// ( $samples $current $target $mutProb $seedState )
|
|
3608
|
-
// string:mutateSelectBest
|
|
3609
|
-
// ( $best $bestScore $seedState2 )
|
|
3610
|
-
//
|
|
3611
|
-
// Deterministic 31-bit LCG (same as the GA demo):
|
|
3612
|
-
// state = (1103515245 * state + 12345) % 2^31
|
|
3613
|
-
// and randRound(N) = Math.round((state/2^31) * N) with state advanced once per draw.
|
|
3614
|
-
if (pv === STRING_NS + 'mutateSelectBest') {
|
|
3615
|
-
if (!(g.s instanceof ListTerm) || g.s.elems.length !== 5) return [];
|
|
3616
|
-
|
|
3617
|
-
const samplesNum = parseNum(g.s.elems[0]);
|
|
3618
|
-
const current = termToJsXsdStringNoLang(g.s.elems[1]);
|
|
3619
|
-
const target = termToJsXsdStringNoLang(g.s.elems[2]);
|
|
3620
|
-
const mutProbNum = parseNum(g.s.elems[3]);
|
|
3621
|
-
const seedNum = parseNum(g.s.elems[4]);
|
|
3622
|
-
|
|
3623
|
-
if (samplesNum === null || current === null || target === null || mutProbNum === null || seedNum === null)
|
|
3624
|
-
return [];
|
|
3625
|
-
if (current.length !== target.length) return [];
|
|
3626
|
-
|
|
3627
|
-
const samples = Math.max(1, Math.trunc(samplesNum));
|
|
3628
|
-
const mutProb = Math.max(0, Math.trunc(mutProbNum));
|
|
3629
|
-
const seed0 = Math.trunc(seedNum);
|
|
3630
|
-
|
|
3631
|
-
let state = BigInt(seed0);
|
|
3632
|
-
const MOD = 2147483648n; // 2^31
|
|
3633
|
-
const A = 1103515245n;
|
|
3634
|
-
const C = 12345n;
|
|
3635
|
-
|
|
3636
|
-
function rnd() {
|
|
3637
|
-
state = (A * state + C) % MOD;
|
|
3638
|
-
return Number(state) / 2147483648;
|
|
3639
|
-
}
|
|
3640
|
-
|
|
3641
|
-
function randRound(N) {
|
|
3642
|
-
return Math.round(rnd() * N);
|
|
3643
|
-
}
|
|
3644
|
-
|
|
3645
|
-
function randomAlpha() {
|
|
3646
|
-
const p = randRound(26);
|
|
3647
|
-
return p === 0 ? ' ' : String.fromCharCode(64 + p);
|
|
3648
|
-
}
|
|
3649
|
-
|
|
3650
|
-
function mutate(str) {
|
|
3651
|
-
let out = '';
|
|
3652
|
-
for (let i = 0; i < str.length; i++) {
|
|
3653
|
-
const p = randRound(100);
|
|
3654
|
-
if (p > mutProb) out += str[i];
|
|
3655
|
-
else out += randomAlpha();
|
|
3656
|
-
}
|
|
3657
|
-
return out;
|
|
3658
|
-
}
|
|
3659
|
-
|
|
3660
|
-
function score(str) {
|
|
3661
|
-
let diffs = 0;
|
|
3662
|
-
for (let i = 0; i < target.length; i++) if (str[i] !== target[i]) diffs++;
|
|
3663
|
-
return diffs;
|
|
3664
|
-
}
|
|
3665
|
-
|
|
3666
|
-
let best = '';
|
|
3667
|
-
let bestScore = Infinity;
|
|
3668
|
-
|
|
3669
|
-
for (let i = 0; i < samples; i++) {
|
|
3670
|
-
const cand = mutate(current);
|
|
3671
|
-
const candScore = score(cand);
|
|
3672
|
-
if (candScore < bestScore) {
|
|
3673
|
-
best = cand;
|
|
3674
|
-
bestScore = candScore;
|
|
3675
|
-
}
|
|
3676
|
-
}
|
|
3677
|
-
|
|
3678
|
-
const outList = new ListTerm([
|
|
3679
|
-
makeStringLiteral(best),
|
|
3680
|
-
internLiteral(String(bestScore)),
|
|
3681
|
-
internLiteral(state.toString()),
|
|
3682
|
-
]);
|
|
3683
|
-
|
|
3684
|
-
const s2 = unifyTerm(g.o, outList, subst);
|
|
3685
|
-
return s2 !== null ? [s2] : [];
|
|
3686
|
-
}
|
|
3687
|
-
|
|
3688
3601
|
// Unknown builtin
|
|
3689
3602
|
return [];
|
|
3690
3603
|
}
|
package/lib/cli.js
CHANGED
|
@@ -71,7 +71,7 @@ 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)
|
|
74
|
+
` -r, --strings Print log:outputString strings (ordered by key), including via log:query.\n` +
|
|
75
75
|
` -s, --super-restricted Disable all builtins except => and <=.\n` +
|
|
76
76
|
` -t, --stream Stream derived triples as soon as they are derived.\n` +
|
|
77
77
|
` -v, --version Print version and exit.\n`;
|
|
@@ -181,8 +181,21 @@ function main() {
|
|
|
181
181
|
// If requested, print log:outputString values (ordered by subject key) and exit.
|
|
182
182
|
// Note: log:outputString values may depend on derived facts, so we must saturate first.
|
|
183
183
|
if (outputStringsMode) {
|
|
184
|
-
|
|
185
|
-
|
|
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);
|
|
192
|
+
outTriples = res.queryTriples;
|
|
193
|
+
} else {
|
|
194
|
+
engine.forwardChain(facts, frules, brules);
|
|
195
|
+
outTriples = facts;
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
const out = engine.collectOutputStringsFromFacts(outTriples, prefixes);
|
|
186
199
|
if (out) process.stdout.write(out);
|
|
187
200
|
process.exit(0);
|
|
188
201
|
}
|