eyeling 1.14.0 → 1.14.2
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 +19 -19
- package/examples/ackermann.n3 +11 -4
- package/examples/genetic-algorithm.n3 +136 -22
- package/examples/output/ackermann.n3 +1 -0
- package/eyeling-builtins.ttl +6 -5
- package/eyeling.js +135 -109
- package/lib/builtins.js +135 -109
- package/package.json +1 -1
package/HANDBOOK.md
CHANGED
|
@@ -969,7 +969,9 @@ If the types don’t fit any supported case, the builtin fails.
|
|
|
969
969
|
|
|
970
970
|
**Shape:** `( $base $exp ) math:exponentiation $result`
|
|
971
971
|
|
|
972
|
-
- Forward direction
|
|
972
|
+
- Forward direction supports two modes:
|
|
973
|
+
- **Exact integer mode (BigInt):** if `$base` and `$exp` are integer literals and `$exp >= 0`, Eyeling computes the exact integer power using BigInt (with a safety cap on the estimated result size to avoid OOM).
|
|
974
|
+
- **Numeric mode (Number):** otherwise, if base and exponent parse as finite Numbers, computes `base ** exp`.
|
|
973
975
|
- Reverse direction (limited): Eyeling can sometimes solve for the exponent if:
|
|
974
976
|
- base and result are numeric, finite, and **positive**
|
|
975
977
|
- base is not 1
|
|
@@ -977,6 +979,16 @@ If the types don’t fit any supported case, the builtin fails.
|
|
|
977
979
|
|
|
978
980
|
This is a pragmatic inversion, not a full algebra system.
|
|
979
981
|
|
|
982
|
+
#### `math:bigExponentiation`
|
|
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).
|
|
991
|
+
|
|
980
992
|
#### Unary “math relations” (often invertible)
|
|
981
993
|
|
|
982
994
|
Eyeling implements these as a shared pattern: if the subject is numeric, compute object; else if the object is numeric, compute subject via an inverse function; if both sides are unbound, succeed once (don’t enumerate).
|
|
@@ -1551,6 +1563,12 @@ If `i` is out of range, `out` is the original string.
|
|
|
1551
1563
|
|
|
1552
1564
|
Returns the number of differing positions between `a` and `b`. Fails if the two strings have different lengths.
|
|
1553
1565
|
|
|
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
|
+
|
|
1554
1572
|
### Containment and prefix/suffix tests
|
|
1555
1573
|
|
|
1556
1574
|
- `string:contains`
|
|
@@ -1976,24 +1994,6 @@ References:
|
|
|
1976
1994
|
|
|
1977
1995
|
If you are running untrusted inputs, consider `--super-restricted` to disable all builtins except implication.
|
|
1978
1996
|
|
|
1979
|
-
### Eyeling fast-path builtins
|
|
1980
|
-
|
|
1981
|
-
Eyeling ships one optional fast-path builtins builtin e.g. used by the genetic-algorithm example:
|
|
1982
|
-
|
|
1983
|
-
#### `urn:eyeling:ga:solveString`
|
|
1984
|
-
|
|
1985
|
-
**Shape:** `( target mutationProbability samples seed traceEvery maxGenerations ) urn:eyeling:ga:solveString ( generation score value seed )`
|
|
1986
|
-
|
|
1987
|
-
- `target` and `value` are `xsd:string` literals.
|
|
1988
|
-
- `mutationProbability` is interpreted as a percentage per character (0–100).
|
|
1989
|
-
- `traceEvery` controls debug tracing:
|
|
1990
|
-
- `0` disables tracing,
|
|
1991
|
-
- `1` traces every generation,
|
|
1992
|
-
- `N` traces every `N` generations.
|
|
1993
|
-
- `maxGenerations` is a safety cap:
|
|
1994
|
-
- `0` means unlimited,
|
|
1995
|
-
- otherwise the builtin stops once `generation >= maxGenerations` (even if not solved).
|
|
1996
|
-
|
|
1997
1997
|
### A.6 Skolemization and `log:skolem`
|
|
1998
1998
|
|
|
1999
1999
|
When forward rule heads contain blank nodes (existentials), Eyeling replaces them with generated Skolem IRIs so derived facts are ground.
|
package/examples/ackermann.n3
CHANGED
|
@@ -39,17 +39,24 @@
|
|
|
39
39
|
(?Y ?Z) math:product ?A.
|
|
40
40
|
}.
|
|
41
41
|
|
|
42
|
+
# exponentiation (x=3) — use BigInt exponentiation builtin to avoid blow-up
|
|
43
|
+
{
|
|
44
|
+
(3 ?Y ?Z) :ackermann ?A.
|
|
45
|
+
} <= {
|
|
46
|
+
(?Z ?Y) math:bigExponentiation ?A.
|
|
47
|
+
}.
|
|
48
|
+
|
|
42
49
|
# exponentiation (x=3), tetration (x=4), pentation (x=5), hexation (x=6), etc
|
|
43
50
|
{
|
|
44
51
|
(?X 0 ?Z) :ackermann 1.
|
|
45
52
|
} <= {
|
|
46
|
-
?X math:greaterThan
|
|
53
|
+
?X math:greaterThan 3.
|
|
47
54
|
}.
|
|
48
55
|
|
|
49
56
|
{
|
|
50
57
|
(?X ?Y ?Z) :ackermann ?A.
|
|
51
58
|
} <= {
|
|
52
|
-
?X math:greaterThan
|
|
59
|
+
?X math:greaterThan 3.
|
|
53
60
|
?Y math:notEqualTo 0.
|
|
54
61
|
(?Y 1) math:difference ?B.
|
|
55
62
|
(?X ?B ?Z) :ackermann ?C.
|
|
@@ -69,7 +76,7 @@
|
|
|
69
76
|
(3 1000) :ackermann ?A7.
|
|
70
77
|
(4 0) :ackermann ?A8.
|
|
71
78
|
(4 1) :ackermann ?A9.
|
|
72
|
-
|
|
79
|
+
(4 2) :ackermann ?A10.
|
|
73
80
|
(5 0) :ackermann ?A11.
|
|
74
81
|
} => {
|
|
75
82
|
:test :is {
|
|
@@ -83,7 +90,7 @@
|
|
|
83
90
|
(3 1000) :ackermann ?A7.
|
|
84
91
|
(4 0) :ackermann ?A8.
|
|
85
92
|
(4 1) :ackermann ?A9.
|
|
86
|
-
|
|
93
|
+
(4 2) :ackermann ?A10.
|
|
87
94
|
(5 0) :ackermann ?A11.
|
|
88
95
|
}.
|
|
89
96
|
}.
|
|
@@ -10,46 +10,158 @@
|
|
|
10
10
|
# This is a simple hill-climbing GA (selection + mutation, no crossover), using a seeded RNG
|
|
11
11
|
# so runs are reproducible.
|
|
12
12
|
#
|
|
13
|
-
#
|
|
14
|
-
#
|
|
13
|
+
# The GA is still expressed as backward rules (<=) for the outer evolution loop,
|
|
14
|
+
# but the expensive inner loop ("take N mutated samples and keep the best") is
|
|
15
|
+
# handled by a single string builtin to avoid huge proof trees and OOM.
|
|
15
16
|
#
|
|
16
|
-
# Configure:
|
|
17
|
-
# :mutationProbability 5 # percent per character
|
|
18
|
-
# :samples 80
|
|
19
|
-
# :seed 100
|
|
20
|
-
# :traceEvery 0 # 0=off, 1=every generation, 100=every 100 generations
|
|
21
|
-
# :maxGenerations 0 # 0=unlimited
|
|
22
17
|
# ==========================================================================================
|
|
23
18
|
|
|
24
|
-
@prefix : <
|
|
25
|
-
@prefix ega: <urn:eyeling:ga:>.
|
|
19
|
+
@prefix : <urn:ga:>.
|
|
26
20
|
@prefix log: <http://www.w3.org/2000/10/swap/log#>.
|
|
21
|
+
@prefix math: <http://www.w3.org/2000/10/swap/math#>.
|
|
22
|
+
@prefix list: <http://www.w3.org/2000/10/swap/list#>.
|
|
27
23
|
@prefix string: <http://www.w3.org/2000/10/swap/string#>.
|
|
28
24
|
|
|
29
25
|
:cfg
|
|
30
26
|
:mutationProbability 5;
|
|
31
27
|
:samples 80;
|
|
32
28
|
:seed 100;
|
|
33
|
-
:traceEvery 1;
|
|
34
|
-
:maxGenerations 0.
|
|
35
29
|
|
|
36
|
-
#
|
|
37
|
-
|
|
30
|
+
# Debug knobs:
|
|
31
|
+
:traceEvery 1; # 0 disables; 1 traces every generation
|
|
32
|
+
:maxGenerations 0; # 0 means unlimited
|
|
33
|
+
|
|
34
|
+
:alphabet (" " "A" "B" "C" "D" "E" "F" "G" "H" "I" "J" "K" "L" "M"
|
|
35
|
+
"N" "O" "P" "Q" "R" "S" "T" "U" "V" "W" "X" "Y" "Z").
|
|
36
|
+
|
|
37
|
+
# ------------------------
|
|
38
|
+
# Small arithmetic helpers
|
|
39
|
+
# ------------------------
|
|
40
|
+
|
|
41
|
+
{ ( ?N 1 ) :dec ?N1 } <= { ( ?N 1 ) math:difference ?N1 }.
|
|
42
|
+
{ ( ?N 1 ) :inc ?N1 } <= { ( ?N 1 ) math:sum ?N1 }.
|
|
43
|
+
|
|
44
|
+
# ----------------------------------------------
|
|
45
|
+
# Seeded RNG (LCG) and JS Math.round(rnd() * N)
|
|
46
|
+
# (Used only for the initial random chromosome.)
|
|
47
|
+
# ----------------------------------------------
|
|
48
|
+
|
|
49
|
+
{ ?S0 :lcgNext ?S1 } <= {
|
|
50
|
+
( ?S0 1103515245 ) math:product ?P .
|
|
51
|
+
( ?P 12345 ) math:sum ?T .
|
|
52
|
+
( ?T 2147483648 ) math:remainder ?S1
|
|
53
|
+
}.
|
|
54
|
+
|
|
55
|
+
{ ( ?S0 ?N ) :randRound ( ?R ?S1 ) } <= {
|
|
56
|
+
?S0 :lcgNext ?S1 .
|
|
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
|
|
62
|
+
}.
|
|
63
|
+
|
|
64
|
+
{ ?S0 :randomAlpha ( ?Ch ?S1 ) } <= {
|
|
65
|
+
:cfg :alphabet ?Alphabet .
|
|
66
|
+
( ?S0 26 ) :randRound ( ?Idx ?S1 ) .
|
|
67
|
+
( ?Alphabet ?Idx ) list:memberAt ?Ch
|
|
68
|
+
}.
|
|
69
|
+
|
|
70
|
+
{ ( 0 ?S0 ) :randomText ( "" ?S0 ) } <= true.
|
|
71
|
+
|
|
72
|
+
{ ( ?Len ?S0 ) :randomText ( ?Out ?S2 ) } <= {
|
|
73
|
+
?Len math:greaterThan 0 .
|
|
74
|
+
( ?Len 1 ) :dec ?Len1 .
|
|
75
|
+
?S0 :randomAlpha ( ?Ch ?S1 ) .
|
|
76
|
+
( ?Len1 ?S1 ) :randomText ( ?Rest ?S2 ) .
|
|
77
|
+
( "%s%s" ?Ch ?Rest ) string:format ?Out
|
|
78
|
+
}.
|
|
79
|
+
|
|
80
|
+
# -------------------------
|
|
81
|
+
# tracing helper (optional)
|
|
82
|
+
# -------------------------
|
|
83
|
+
|
|
84
|
+
{ ( 0 ?Gen ?Score ?Value ) :traceMaybe true } <= true.
|
|
85
|
+
|
|
86
|
+
{ ( ?Every ?Gen ?Score ?Value ) :traceMaybe true } <= {
|
|
87
|
+
?Every math:greaterThan 0 .
|
|
88
|
+
( ?Gen ?Every ) math:remainder ?R .
|
|
89
|
+
?R math:equalTo 0 .
|
|
90
|
+
?Gen log:trace ( ?Score ?Value )
|
|
91
|
+
}.
|
|
92
|
+
|
|
93
|
+
# --------------
|
|
94
|
+
# evolution loop
|
|
95
|
+
# --------------
|
|
96
|
+
|
|
97
|
+
# Stop when score == 0
|
|
98
|
+
{ ( ?Current 0 ?Target ?MutProb ?Samples ?Gen ?S0 ?MaxGen ?TraceEvery )
|
|
99
|
+
:evolve ( ?Current ?Gen ?S0 ) } <= true.
|
|
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
|
|
107
|
+
}.
|
|
108
|
+
|
|
109
|
+
# Unlimited run (MaxGen == 0): keep evolving
|
|
110
|
+
{ ( ?Current ?Score ?Target ?MutProb ?Samples ?Gen ?S0 0 ?TraceEvery )
|
|
111
|
+
:evolve ( ?Final ?FinalGen ?S2 ) } <= {
|
|
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 )
|
|
120
|
+
}.
|
|
121
|
+
|
|
122
|
+
# Bounded run (MaxGen > 0): keep evolving while Gen < MaxGen
|
|
123
|
+
{ ( ?Current ?Score ?Target ?MutProb ?Samples ?Gen ?S0 ?MaxGen ?TraceEvery )
|
|
124
|
+
:evolve ( ?Final ?FinalGen ?S2 ) } <= {
|
|
125
|
+
?Score math:notEqualTo 0 .
|
|
126
|
+
?MaxGen math:greaterThan 0 .
|
|
127
|
+
?Gen math:lessThan ?MaxGen .
|
|
128
|
+
( ?Samples ?Current ?Target ?MutProb ?S0 )
|
|
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
|
+
}.
|
|
136
|
+
|
|
137
|
+
# ----------------------------------
|
|
138
|
+
# Public solver wrapper (string API)
|
|
139
|
+
# ----------------------------------
|
|
140
|
+
|
|
141
|
+
{ ?TargetString :solveResult ( ?Gen 0 ?Value ?Seed ) } <= {
|
|
38
142
|
:cfg :mutationProbability ?MutProb;
|
|
39
143
|
:samples ?Samples;
|
|
40
144
|
:seed ?Seed;
|
|
41
145
|
:traceEvery ?TraceEvery;
|
|
42
|
-
:maxGenerations ?
|
|
146
|
+
:maxGenerations ?MaxGen.
|
|
147
|
+
|
|
148
|
+
?TargetString string:length ?Len .
|
|
149
|
+
|
|
150
|
+
( ?Len ?Seed ) :randomText ( ?Current0 ?S1 ) .
|
|
151
|
+
|
|
152
|
+
# initial score using string:hammingDistance
|
|
153
|
+
( ?Current0 ?TargetString ) string:hammingDistance ?Score0 .
|
|
43
154
|
|
|
44
|
-
( ?TargetString ?MutProb ?Samples ?
|
|
45
|
-
|
|
46
|
-
( ?
|
|
155
|
+
( ?Current0 ?Score0 ?TargetString ?MutProb ?Samples 0 ?S1 ?MaxGen ?TraceEvery )
|
|
156
|
+
:evolve
|
|
157
|
+
( ?Value ?Gen ?S2 ) .
|
|
47
158
|
|
|
48
|
-
#
|
|
49
|
-
?
|
|
159
|
+
# Succeeds only when solved:
|
|
160
|
+
( ?Value ?TargetString ) string:hammingDistance 0 .
|
|
161
|
+
?Value log:equalTo ?TargetString .
|
|
162
|
+
?S2 log:equalTo ?_FinalSeedState
|
|
50
163
|
}.
|
|
51
164
|
|
|
52
|
-
# Boolean-ish API for querying success
|
|
53
165
|
{ ?TargetString :solved true } <= {
|
|
54
166
|
?TargetString :solveResult ( ?Gen 0 ?TargetString ?Seed )
|
|
55
167
|
}.
|
|
@@ -60,4 +172,6 @@
|
|
|
60
172
|
|
|
61
173
|
{ "METHINKS IT IS LIKE A WEASEL" :solved true .
|
|
62
174
|
( "solve('%s').\n" "METHINKS IT IS LIKE A WEASEL" ) string:format ?Line
|
|
63
|
-
}
|
|
175
|
+
}
|
|
176
|
+
log:query
|
|
177
|
+
{ 1 log:outputString ?Line }.
|
|
@@ -11,5 +11,6 @@
|
|
|
11
11
|
(3 1000) :ackermann 85720688574901385675874003924800144844912384936442688595500031069628084089994889799455870305255668650207573833404251746014971622855385123487876620597588598431476542198593847883368596840498969135023633457224371799868655530139190140473324351568616503316569571821492337341283438653220995094697645344555005 .
|
|
12
12
|
(4 0) :ackermann 13 .
|
|
13
13
|
(4 1) :ackermann 65533 .
|
|
14
|
+
(4 2) :ackermann 2003529930406846464979072351560255750447825475569751419265016973710894059556311453089506130880933348101038234342907263181822949382118812668869506364761547029165041871916351587966347219442930927982084309104855990570159318959639524863372367203002916969592156108764948889254090805911457037675208500206671563702366126359747144807111774815880914135742720967190151836282560618091458852699826141425030123391108273603843767876449043205960379124490905707560314035076162562476031863793126484703743782954975613770981604614413308692118102485959152380195331030292162800160568670105651646750568038741529463842244845292537361442533614373729088303794601274724958414864915930647252015155693922628180691650796381064132275307267143998158508811292628901134237782705567421080070065283963322155077831214288551675554073345107213112427399562982719769150054883905223804357045848197956393157853510018992000024141963706813559840464039472194016069517690156119726982337890017641517190051133466306898140219383481435426387306539552969691388024158161859561100640362119796101859534802787167200122604642492385111393400464351623867567078745259464670903886547743483217897012764455529409092021959585751622973333576159552394885297579954028471943529913543763705986928913757153740001986394332464890052543106629669165243419174691389632476560289415199775477703138064781342309596190960654591300890188887588084733625956065444888501447335706058817090162108499714529568344061979690565469813631162053579369791403236328496233046421066136200220175787851857409162050489711781820400187282939943446186224328009837323764931814789848119452713007440220765680910376203999203492023906626264491909167985461515778839060397720759279378852241294301017458086862263369284725851403039615558564330385450688652213114813638408384778263790459607186876728509763471271988890680478243230394718650525660978150729861141430305816927924971409161059417185352275887504477592218301158780701975535722241400019548102005661773589781499532325208589753463547007786690406429016763808161740550405117670093673202804549339027992491867306539931640720492238474815280619166900933805732120816350707634351669869625020969023162859350071874190579161241536897514808261904847946571736601005892476655445840838334790544144817684255327207315586349347605137419779525190365032198020108764738368682531025183377533908861426184800374008082238104076468878471647552945326947661700424461063311238021134588694532200116564076327023074292426051582811070387018345324567635625951430032037432740780879056283663406965030844225855967039271869461158513793386475699748568670079823960604393478850861649260304945061743412365828352144806726676841807083754862211408236579802961200027441324438432402331257403545019352428776430880232850855886089962774458164680857875115807014743763867976955049991643998284357290415378143438847303484261903388841494031366139854257635577105335580206622185577060082551288893332226436281984838613239570676191409638533832374343758830859233722284644287996245605476932428998432652677378373173288063210753211238680604674708428051166488709084770291208161104912555598322366244868556651402684641209694982590565519216188104341226838996283071654868525536914850299539675503954938371853405900096187489473992880432496373165753803673586710175783994818471798498246948060532081996066183434012476096639519778021441199752546704080608499344178256285092726523709898651539462193004607364507926212975917698293892367015170992091531567814439791248475706237804600009918293321306880570046591458387208088016887445835557926258465124763087148566313528934166117490617526671492672176128330845273936469244582892571388877839056300482483799839692029222215486145902373478222682521639957440801727144146179559226175083889020074169926238300282286249284182671243405751424188569994272331606998712986882771820617214453142574944015066139463169197629181506579745526236191224848063890033669074365989226349564114665503062965960199720636202603521917776740668777463549375318899587866282125469797102065747232721372918144666659421872003474508942830911535189271114287108376159222380276605327823351661555149369375778466670145717971901227117812780450240026384758788339396817962950690798817121690686929538248529830023476068454114178139110648560236549754227497231007615131870024053910510913817843721791422528587432098524957878034683703337818421444017138688124249984418618129271198533315382567321870421530631197748535214670955334626336610864667332292409879849256691109516143618601548909740241913509623043612196128165950518666022030715613684732364660868905014263913906515063908199378852318365059897299125404479443425166774299659811849233151555272883274028352688442408752811283289980625912673699546247341543333500147231430612750390307397135252069338173843322950701049061867539433130784798015655130384758155685236218010419650255596181934986315913233036096461905990236112681196023441843363334594927631946101716652913823717182394299216272538461776065694542297877071383198817036964588689811863210976900355735884624464835706291453052757101278872027965364479724025405448132748391794128826423835171949197209797145936887537198729130831738033911016128547415377377715951728084111627597186384924222802373441925469991983672192131287035585307966942713416391033882754318613643490100943197409047331014476299861725424423355612237435715825933382804986243892498222780715951762757847109475119033482241412025182688713728193104253478196128440176479531505057110722974314569915223451643121848657575786528197564843508958384722923534559464521215831657751471298708225909292655638836651120681943836904116252668710044560243704200663709001941185557160472044643696932850060046928140507119069261393993902735534545567470314903886022024639948260501762431969305640666366626090207048887438898907498152865444381862917382901051820869936382661868303915273264581286782806601337500096593364625146091723180312930347877421234679118454791311109897794648216922505629399956793483801699157439700537542134485874586856047286751065423341893839099110586465595113646061055156838541217459801807133163612573079611168343863767667307354583494789788316330129240800836356825939157113130978030516441716682518346573675934198084958947940983292500086389778563494693212473426103062713745077286156922596628573857905533240641849018451328284632709269753830867308409142247659474439973348130810986399417379789657010687026734161967196591599588537834822988270125605842365589539690306474965584147981310997157542043256395776070485100881578291408250777738559790129129407309462785944505859412273194812753225152324801503466519048228961406646890305102510916237770448486230229488966711380555607956620732449373374027836767300203011615227008921843515652121379215748206859356920790214502277133099987729459596952817044582181956080965811702798062669891205061560742325686842271306295009864421853470810407128917646906550836129916694778023822502789667843489199409657361704586786242554006942516693979292624714524945408858422726153755260071904336329196375777502176005195800693847635789586878489536872122898557806826518192703632099480155874455575175312736471421295536494084385586615208012115079075068553344489258693283859653013272046970694571546959353658571788894862333292465202735853188533370948455403336565356988172582528918056635488363743793348411845580168331827676834646291995605513470039147876808640322629616641560667508153710646723108461964247537490553744805318226002710216400980584497526023035640038083472053149941172965736785066421400842696497103241919182121213206939769143923368374709228267738708132236680086924703491586840991153098315412063566123187504305467536983230827966457417620806593177265685841681837966106144963432544111706941700222657817358351259821080769101961052229263879745049019254311900620561906577452416191913187533984049343976823310298465893318373015809592522829206820862230332585280119266496314441316442773003237792274712330696417149945532261035475145631290668854345426869788447742981777493710117614651624183616680254815296335308490849943006763654806102940094693750609845588558043970485914449584445079978497045583550685408745163316464118083123079704389849190506587586425810738422420591191941674182490452700288263983057950057341711487031187142834184499153456702915280104485145176055306971441761368582384102787659324662689978418319620312262421177391477208004883578333569204533935953254564897028558589735505751235129536540502842081022785248776603574246366673148680279486052445782673626230852978265057114624846595914210278122788941448163994973881884622768244851622051817076722169863265701654316919742651230041757329904473537672536845792754365412826553581858046840069367718605020070547247548400805530424951854495267247261347318174742180078574693465447136036975884118029408039616746946288540679172138601225419503819704538417268006398820656328792839582708510919958839448297775647152026132871089526163417707151642899487953564854553553148754978134009964854498635824847690590033116961303766127923464323129706628411307427046202032013368350385425360313636763575212604707425311209233402837482949453104727418969287275572027615272268283376741393425652653283068469997597097750005560889932685025049212884068274139881631540456490350775871680074055685724021758685439053228133770707415830756269628316955687424060527726485853050611356384851965918968649596335568216975437621430778665934730450164822432964891270709898076676625671517269062058815549666382573829274182082278960684488222983394816670984039024283514306813767253460126007269262969468672750794346190439996618979611928750519442356402644303271737341591281496056168353988188569484045342311424613559925272330064881627466723523751234311893442118885085079358163848994487544756331689213869675574302737953785262542329024881047181939037220666894702204258836895840939998453560948869946833852579675161882159410981624918741813364726965123980677561947912557957446471427868624053750576104204267149366084980238274680575982591331006919941904651906531171908926077949119217946407355129633864523035673345588033313197080365457184791550432654899559705862888286866606618021882248602144999973122164138170653480175510438406624412822803616648904257377640956326482825258407669045608439490325290526337532316509087681336614242398309530806549661879381949120033919489494065132398816642080088395554942237096734840072642705701165089075196155370186264797456381187856175457113400473810762763014953309735174180655479112660938034311378532532883533352024934365979129341284854970946826329075830193072665337782559314331110963848053940859283988907796210479847919686876539987477095912788727475874439806779824968278272200926449944559380414608770641941810440758269805688038949654616587983904660587645341810289907194293021774519976104495043196841503455514044820928933378657363052830619990077748726922998608279053171691876578860908941817057993404890218441559791092676862796597583952483926734883634745651687016166240642424241228961118010615682342539392180052483454723779219911228595914191877491793823340010078128326506710281781396029120914720100947878752551263372884222353869490067927664511634758101193875319657242121476038284774774571704578610417385747911301908583877890152334343013005282797038580359815182929600305682612091950943737325454171056383887047528950563961029843641360935641632589408137981511693338619797339821670761004607980096016024823096943043806956620123213650140549586250615282588033022908385812478469315720323233601899469437647726721879376826431828382603564520699468630216048874528424363593558622333506235945002890558581611275341783750455936126130852640828051213873177490200249552738734585956405160830583053770732533971552620444705429573538361113677523169972740292941674204423248113875075631319078272188864053374694213842169928862940479635305150560788126366206497231257579019598873041195626227343728900516561111094111745277965482790471250581999077498063821559376885546498822938985408291325129076478386322494781016753491693489288104203015610283386143827378160946341335383578340765314321417150655877547820252454780657301342277470616744241968952613164274104695474621483756288299771804186785084546965619150908695874251184435837306590951460980451247409411373899927822492983367796011015387096129749705566301637307202750734759922943792393824427421186158236161317886392553095117188421298508307238259729144142251579403883011359083331651858234967221259621812507058113759495525022747274674369887131926670769299199084467161228738858457584622726573330753735572823951616964175198675012681745429323738294143824814377139861906716657572945807804820559511881687188075212971832636442155336787751274766940790117057509819575084563565217389544179875074523854455200133572033332379895074393905312918212255259833790909463630202185353848854825062897715616963860712382771725621313460549401770413581731931763370136332252819127547191443450920711848838366818174263342949611870091503049165339464763717766439120798347494627397822171502090670190302469762151278521956142070806461631373236517853976292092025500288962012970141379640038055734949269073535145961208674796547733692958773628635660143767964038430796864138563447801328261284589184898528048048844180821639423974014362903481665458114454366460032490618763039502356402044530748210241366895196644221339200757479128683805175150634662569391937740283512075666260829890491877287833852178522792045771846965855278790447562192663992008409302075673925363735628390829817577902153202106409617373283598494066652141198183810884515459772895164572131897797907491941013148368544639616904607030107596818933741217575988165127000761262789169510406315857637534787420070222051070891257612361658026806815858499852631465878086616800733264676830206391697203064894405628195406190685242003053463156621891327309069687353181641094514288036605995220248248886711554429104721929134248346438705368508648749099178812670565665387191049721820042371492740164460943459845392536706132210616533085662021188968234005752675486101476993688738209584552211571923479686888160853631615862880150395949418529489227074410828207169303387818084936204018255222271010985653444817207470756019245915599431072949578197878590578940052540122867517142511184356437184053563024181225473266093302710397968091064939272722683035410467632591355279683837705019855234621222858410557119921731717969804339317707750755627056047831779844447637560254637033369247114220815519973691371975163241302748712199863404548248524570118553342675264715978310731245663429805221455494156252724028915333354349341217862037007260315279870771872491234494477147909520734761385425485311552773301030342476835865496093722324007154518129732692081058424090557725645803681462234493189708138897143299831347617799679712453782310703739151473878692119187566700319321281896803322696594459286210607438827416919465162267632540665070881071030394178860564893769816734159025925194611823642945652669372203155504700213598846292758012527715422016629954863130324912311029627923723899766416803497141226527931907636326136814145516376656559839788489381733082668779901962886932296597379951931621187215455287394170243669885593888793316744533363119541518404088283815193421234122820030950313341050704760159987985472529190665222479319715440331794836837373220821885773341623856441380700541913530245943913502554531886454796252260251762928374330465102361057583514550739443339610216229675461415781127197001738611494279501411253280621254775810512972088465263158094806633687670147310733540717710876615935856814098212967730759197382973441445256688770855324570888958320993823432102718224114763732791357568615421252849657903335093152776925505845644010552192644505312073756287744998163646332835816140330175813967359427327690448920361880386754955751806890058532927201493923500525845146706982628548257883267398735220457228239290207144822219885587102896991935873074277815159757620764023951243860202032596596250212578349957710085626386118233813318509014686577064010676278617583772772895892746039403930337271873850536912957126715066896688493880885142943609962012966759079225082275313812849851526902931700263136328942095797577959327635531162066753488651317323872438748063513314512644889967589828812925480076425186586490241111127301357197181381602583178506932244007998656635371544088454866393181708395735780799059730839094881804060935959190907473960904410150516321749681412100765719177483767355751000733616922386537429079457803200042337452807566153042929014495780629634138383551783599764708851349004856973697965238695845994595592090709058956891451141412684505462117945026611750166928260250950770778211950432617383223562437601776799362796099368975191394965033358507155418436456852616674243688920371037495328425927131610537834980740739158633817967658425258036737206469351248652238481341663808061505704829059890696451936440018597120425723007316410009916987524260377362177763430621616744884930810929901009517974541564251204822086714586849255132444266777127863728211331536224301091824391243380214046242223349153559516890816288487989988273630445372432174280215755777967021666317047969728172483392841015642274507271779269399929740308072770395013581545142494049026536105825409373114653104943382484379718606937214444600826798002471229489405761853892203425608302697052876621377373594394224114707074072902725461307358541745691419446487624357682397065703184168467540733466346293673983620004041400714054277632480132742202685393698869787607009590048684650626771363070979821006557285101306601010780633743344773073478653881742681230743766066643312775356466578603715192922768440458273283243808212841218776132042460464900801054731426749260826922155637405486241717031027919996942645620955619816454547662045022411449404749349832206807191352767986747813458203859570413466177937228534940031631599544093684089572533438702986717829770373332806801764639502090023941931499115009105276821119510999063166150311585582835582607179410052528583611369961303442790173811787412061288182062023263849861515656451230047792967563618345768105043341769543067538041113928553792529241347339481050532025708728186307291158911335942014761872664291564036371927602306283840650425441742335464549987055318726887926424102147363698625463747159744354943443899730051742525110877357886390946812096673428152585919924857640488055071329814299359911463239919113959926752576359007446572810191805841807342227734721397723218231771716916400108826112549093361186780575722391018186168549108500885272274374212086524852372456248697662245384819298671129452945515497030585919307198497105414181636968976131126744027009648667545934567059936995464500558921628047976365686133316563907395703272034389175415267500915011198856872708848195531676931681272892143031376818016445477367518353497857924276463354162433601125960252109501612264110346083465648235597934274056868849224458745493776752120324703803035491157544831295275891939893680876327685438769557694881422844311998595700727521393176837831770339130423060958999137314684569010422095161967070506420256733873446115655276175992727151877660010238944760539789516945708802728736225121076224091810066700883474737605156285533943565843756271241244457651663064085939507947550920463932245202535463634444791755661725962187199279186575490857852950012840229035061514937310107009446151011613712423761426722541732055959202782129325725947146417224977321316381845326555279604270541871496236585252458648933254145062642337885651464670604298564781968461593663288954299780722542264790400616019751975007460545150060291806638271497016110987951336633771378434416194053121445291855180136575558667615019373029691932076120009255065081583275508499340768797252369987023567931026804136745718956641431852679054717169962990363015545645090044802789055701968328313630718997699153166679208958768572290600915472919636381673596673959975710326015571920237348580521128117458610065152598883843114511894880552129145775699146577530041384717124577965048175856395072895337539755822087777506072339445587895905719156733 .
|
|
14
15
|
(5 0) :ackermann 65533 .
|
|
15
16
|
} .
|
package/eyeling-builtins.ttl
CHANGED
|
@@ -99,7 +99,10 @@ math:rounded a ex:Builtin ; ex:kind ex:Function ;
|
|
|
99
99
|
rdfs:comment "Rounds subject to nearest integer (JS tie-breaking: toward +∞). Binds/unifies object with the rounded integer value." .
|
|
100
100
|
|
|
101
101
|
math:exponentiation a ex:Builtin ; ex:kind ex:Function ;
|
|
102
|
-
rdfs:comment "Exponentiation. Forward: (base exponent) -> result. Limited inverse: if base is numeric and exponent is a variable, may solve exponent via logs for positive base != 1 and positive result." .
|
|
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
|
+
|
|
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." .
|
|
103
106
|
|
|
104
107
|
math:absoluteValue a ex:Builtin ; ex:kind ex:Function ;
|
|
105
108
|
rdfs:comment "Absolute value. Computes |s| and unifies/binds object; output datatype follows common numeric datatype selection." .
|
|
@@ -346,7 +349,5 @@ string:setCharAt a ex:Builtin ; ex:kind ex:Function ;
|
|
|
346
349
|
string:hammingDistance a ex:Builtin ; ex:kind ex:Function ;
|
|
347
350
|
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." .
|
|
348
351
|
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
ega:solveString a ex:Builtin ; ex:kind ex:Function ;
|
|
352
|
-
rdfs:comment "Eyeling extension: GA solver on strings. Subject list: (target mutationProbability samples seed traceEvery maxGenerations). Object list: (generation score value seed). traceEvery=0 disables tracing; maxGenerations=0 means unlimited." .
|
|
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
|
@@ -64,6 +64,11 @@ const __parseNumericInfoCache = new Map(); // lit string -> info|null
|
|
|
64
64
|
// Caching them retains giant strings/BigInts in global Maps and can cause OOM.
|
|
65
65
|
const MAX_NUMERIC_CACHE_KEY_LEN = 1024;
|
|
66
66
|
|
|
67
|
+
// Safety cap for BigInt exponentiation results.
|
|
68
|
+
// Prevents accidental creation of enormous integers that would OOM the process.
|
|
69
|
+
// (Ackermann(4,2) is ~65k bits, so well below this.)
|
|
70
|
+
const MAX_BIGINT_POW_RESULT_BITS = 2_000_000n;
|
|
71
|
+
|
|
67
72
|
function __useNumericCacheKey(key) {
|
|
68
73
|
return typeof key === 'string' && key.length <= MAX_NUMERIC_CACHE_KEY_LEN;
|
|
69
74
|
}
|
|
@@ -603,6 +608,31 @@ function pow10n(k) {
|
|
|
603
608
|
return 10n ** BigInt(k);
|
|
604
609
|
}
|
|
605
610
|
|
|
611
|
+
function absBigInt(x) {
|
|
612
|
+
return x < 0n ? -x : x;
|
|
613
|
+
}
|
|
614
|
+
|
|
615
|
+
function bigintBitLength(x) {
|
|
616
|
+
// Returns the bit length of |x| as a BigInt (0 for 0).
|
|
617
|
+
const a = absBigInt(x);
|
|
618
|
+
if (a === 0n) return 0n;
|
|
619
|
+
// toString(2) is fine here: we only use this as a conservative size guard.
|
|
620
|
+
return BigInt(a.toString(2).length);
|
|
621
|
+
}
|
|
622
|
+
|
|
623
|
+
function estimatePowResultBits(base, exp) {
|
|
624
|
+
// Conservative estimate of bit length for |base| ** exp (exp >= 0).
|
|
625
|
+
// For |base| in {0,1} this is tiny; otherwise ~ exp * log2(|base|).
|
|
626
|
+
if (exp === 0n) return 1n;
|
|
627
|
+
const a = absBigInt(base);
|
|
628
|
+
if (a === 0n) return 1n; // 0**k (k>0) => 0
|
|
629
|
+
if (a === 1n) return 1n;
|
|
630
|
+
const bl = bigintBitLength(a);
|
|
631
|
+
// If bl is the bit length, then 2^(bl-1) <= a < 2^bl.
|
|
632
|
+
// So a^exp has < bl*exp bits and >= (bl-1)*exp+1 bits.
|
|
633
|
+
return (bl - 1n) * exp + 1n;
|
|
634
|
+
}
|
|
635
|
+
|
|
606
636
|
// ===========================================================================
|
|
607
637
|
// Time & duration builtin helpers
|
|
608
638
|
// ===========================================================================
|
|
@@ -1762,50 +1792,87 @@ function evalBuiltin(goal, subst, facts, backRules, depth, varGen, maxResults) {
|
|
|
1762
1792
|
}
|
|
1763
1793
|
|
|
1764
1794
|
// math:exponentiation
|
|
1765
|
-
|
|
1766
|
-
|
|
1767
|
-
|
|
1768
|
-
|
|
1795
|
+
// math:bigExponentiation (exact-integer BigInt-only variant)
|
|
1796
|
+
if (pv === MATH_NS + 'exponentiation' || pv === MATH_NS + 'bigExponentiation') {
|
|
1797
|
+
const onlyBigInt = pv === MATH_NS + 'bigExponentiation';
|
|
1798
|
+
|
|
1799
|
+
if (!(g.s instanceof ListTerm) || g.s.elems.length !== 2) return [];
|
|
1800
|
+
const baseTerm = g.s.elems[0];
|
|
1801
|
+
const expTerm = g.s.elems[1];
|
|
1802
|
+
|
|
1803
|
+
// 1) Exact integer mode (BigInt): (base exponent) -> result
|
|
1804
|
+
// This avoids huge intermediate derivations for things like Ackermann(4,2).
|
|
1805
|
+
const baseI = parseIntLiteral(baseTerm);
|
|
1806
|
+
const expI = parseIntLiteral(expTerm);
|
|
1807
|
+
if (baseI !== null && expI !== null && expI >= 0n) {
|
|
1808
|
+
// Size guard: refuse powers that would almost certainly OOM.
|
|
1809
|
+
const estBits = estimatePowResultBits(baseI, expI);
|
|
1810
|
+
if (estBits > MAX_BIGINT_POW_RESULT_BITS) return [];
|
|
1811
|
+
|
|
1812
|
+
let out;
|
|
1813
|
+
try {
|
|
1814
|
+
out = baseI ** expI;
|
|
1815
|
+
} catch {
|
|
1816
|
+
return [];
|
|
1817
|
+
}
|
|
1818
|
+
|
|
1819
|
+
const lit = makeNumericOutputLiteral(out, XSD_INTEGER_DT);
|
|
1820
|
+
|
|
1821
|
+
if (g.o instanceof Var) {
|
|
1822
|
+
const s2 = { ...subst };
|
|
1823
|
+
s2[g.o.name] = lit;
|
|
1824
|
+
return [s2];
|
|
1825
|
+
}
|
|
1826
|
+
if (g.o instanceof Blank) return [{ ...subst }];
|
|
1769
1827
|
|
|
1770
|
-
const
|
|
1771
|
-
|
|
1772
|
-
if (a !== null) b = parseNum(expTerm);
|
|
1828
|
+
const oi = parseIntLiteral(g.o);
|
|
1829
|
+
if (oi !== null && oi === out) return [{ ...subst }];
|
|
1773
1830
|
|
|
1774
|
-
|
|
1775
|
-
|
|
1776
|
-
|
|
1777
|
-
if (!Number.isFinite(cVal)) return [];
|
|
1831
|
+
const s2 = unifyTerm(g.o, lit, subst);
|
|
1832
|
+
return s2 !== null ? [s2] : [];
|
|
1833
|
+
}
|
|
1778
1834
|
|
|
1779
|
-
|
|
1780
|
-
|
|
1781
|
-
const lit = makeNumericOutputLiteral(cVal, dtOut);
|
|
1835
|
+
// bigExponentiation is intentionally strict.
|
|
1836
|
+
if (onlyBigInt) return [];
|
|
1782
1837
|
|
|
1783
|
-
|
|
1784
|
-
|
|
1785
|
-
|
|
1786
|
-
|
|
1787
|
-
|
|
1788
|
-
|
|
1789
|
-
|
|
1838
|
+
// 2) Numeric mode (Number): forward + limited inverse
|
|
1839
|
+
const a = parseNum(baseTerm);
|
|
1840
|
+
const b = a !== null ? parseNum(expTerm) : null;
|
|
1841
|
+
|
|
1842
|
+
// Forward
|
|
1843
|
+
if (a !== null && b !== null) {
|
|
1844
|
+
const cVal = a ** b;
|
|
1845
|
+
if (!Number.isFinite(cVal)) return [];
|
|
1846
|
+
|
|
1847
|
+
let dtOut = commonNumericDatatype([baseTerm, expTerm], g.o);
|
|
1848
|
+
if (dtOut === XSD_INTEGER_DT && !Number.isInteger(cVal)) dtOut = XSD_DECIMAL_DT;
|
|
1849
|
+
const lit = makeNumericOutputLiteral(cVal, dtOut);
|
|
1850
|
+
|
|
1851
|
+
if (g.o instanceof Var) {
|
|
1852
|
+
const s2 = { ...subst };
|
|
1853
|
+
s2[g.o.name] = lit;
|
|
1854
|
+
return [s2];
|
|
1790
1855
|
}
|
|
1856
|
+
if (g.o instanceof Blank) return [{ ...subst }];
|
|
1857
|
+
if (numEqualTerm(g.o, cVal)) return [{ ...subst }];
|
|
1858
|
+
}
|
|
1791
1859
|
|
|
1792
|
-
|
|
1793
|
-
|
|
1794
|
-
|
|
1795
|
-
|
|
1796
|
-
|
|
1797
|
-
|
|
1860
|
+
// Inverse: solve exponent using logs (Number mode only)
|
|
1861
|
+
const c = parseNum(g.o);
|
|
1862
|
+
if (a !== null && expTerm instanceof Var && c !== null) {
|
|
1863
|
+
if (a > 0.0 && a !== 1.0 && c > 0.0) {
|
|
1864
|
+
const bVal = Math.log(c) / Math.log(a);
|
|
1865
|
+
if (!Number.isFinite(bVal)) return [];
|
|
1798
1866
|
|
|
1799
|
-
|
|
1800
|
-
|
|
1867
|
+
let dtB = commonNumericDatatype([baseTerm, g.o], expTerm);
|
|
1868
|
+
if (dtB === XSD_INTEGER_DT && !Number.isInteger(bVal)) dtB = XSD_DECIMAL_DT;
|
|
1801
1869
|
|
|
1802
|
-
|
|
1803
|
-
|
|
1804
|
-
|
|
1805
|
-
}
|
|
1870
|
+
const s2 = { ...subst };
|
|
1871
|
+
s2[expTerm.name] = makeNumericOutputLiteral(bVal, dtB);
|
|
1872
|
+
return [s2];
|
|
1806
1873
|
}
|
|
1807
|
-
return [];
|
|
1808
1874
|
}
|
|
1875
|
+
return [];
|
|
1809
1876
|
}
|
|
1810
1877
|
|
|
1811
1878
|
// math:absoluteValue
|
|
@@ -3547,34 +3614,32 @@ function evalBuiltin(goal, subst, facts, backRules, depth, varGen, maxResults) {
|
|
|
3547
3614
|
return s2 !== null ? [s2] : [];
|
|
3548
3615
|
}
|
|
3549
3616
|
|
|
3550
|
-
//
|
|
3551
|
-
//
|
|
3552
|
-
//
|
|
3553
|
-
|
|
3554
|
-
//
|
|
3555
|
-
//
|
|
3556
|
-
//
|
|
3557
|
-
|
|
3558
|
-
|
|
3559
|
-
|
|
3560
|
-
|
|
3561
|
-
|
|
3562
|
-
const samplesNum = parseNum(g.s.elems[
|
|
3563
|
-
const
|
|
3564
|
-
const
|
|
3565
|
-
const
|
|
3566
|
-
|
|
3567
|
-
|
|
3568
|
-
if (
|
|
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 [];
|
|
3569
3638
|
|
|
3570
|
-
const mutProb = Math.max(0, Math.trunc(mutProbNum));
|
|
3571
3639
|
const samples = Math.max(1, Math.trunc(samplesNum));
|
|
3640
|
+
const mutProb = Math.max(0, Math.trunc(mutProbNum));
|
|
3572
3641
|
const seed0 = Math.trunc(seedNum);
|
|
3573
3642
|
|
|
3574
|
-
const traceEvery = Math.max(0, Math.trunc(traceEveryNum));
|
|
3575
|
-
const maxGenerations = Math.max(0, Math.trunc(maxGenNum));
|
|
3576
|
-
|
|
3577
|
-
// Deterministic 31-bit LCG using BigInt arithmetic (matches the N3 version)
|
|
3578
3643
|
let state = BigInt(seed0);
|
|
3579
3644
|
const MOD = 2147483648n; // 2^31
|
|
3580
3645
|
const A = 1103515245n;
|
|
@@ -3594,12 +3659,6 @@ function evalBuiltin(goal, subst, facts, backRules, depth, varGen, maxResults) {
|
|
|
3594
3659
|
return p === 0 ? ' ' : String.fromCharCode(64 + p);
|
|
3595
3660
|
}
|
|
3596
3661
|
|
|
3597
|
-
function randomText(len) {
|
|
3598
|
-
let out = '';
|
|
3599
|
-
for (let i = 0; i < len; i++) out += randomAlpha();
|
|
3600
|
-
return out;
|
|
3601
|
-
}
|
|
3602
|
-
|
|
3603
3662
|
function mutate(str) {
|
|
3604
3663
|
let out = '';
|
|
3605
3664
|
for (let i = 0; i < str.length; i++) {
|
|
@@ -3616,50 +3675,22 @@ function evalBuiltin(goal, subst, facts, backRules, depth, varGen, maxResults) {
|
|
|
3616
3675
|
return diffs;
|
|
3617
3676
|
}
|
|
3618
3677
|
|
|
3619
|
-
|
|
3620
|
-
|
|
3621
|
-
const genLit = internLiteral(String(gen));
|
|
3622
|
-
const scLit = internLiteral(String(sc));
|
|
3623
|
-
const valLit = makeStringLiteral(val);
|
|
3624
|
-
const obj = new ListTerm([scLit, valLit]);
|
|
3625
|
-
const xStr = termToN3(genLit, pref);
|
|
3626
|
-
const yStr = termToN3(obj, pref);
|
|
3627
|
-
trace.writeTraceLine(`${xStr} TRACE ${yStr}`);
|
|
3628
|
-
}
|
|
3629
|
-
|
|
3630
|
-
let generation = 0;
|
|
3631
|
-
let current = randomText(target.length);
|
|
3632
|
-
let currentScore = score(current);
|
|
3633
|
-
|
|
3634
|
-
if (traceEvery > 0 && generation % traceEvery === 0) doTrace(generation, currentScore, current);
|
|
3635
|
-
|
|
3636
|
-
while (currentScore !== 0) {
|
|
3637
|
-
if (maxGenerations > 0 && generation >= maxGenerations) break;
|
|
3638
|
-
|
|
3639
|
-
let best = '';
|
|
3640
|
-
let bestScore = Infinity;
|
|
3641
|
-
|
|
3642
|
-
for (let i = 0; i < samples; i++) {
|
|
3643
|
-
const cand = mutate(current);
|
|
3644
|
-
const candScore = score(cand);
|
|
3645
|
-
if (candScore < bestScore) {
|
|
3646
|
-
best = cand;
|
|
3647
|
-
bestScore = candScore;
|
|
3648
|
-
}
|
|
3649
|
-
}
|
|
3650
|
-
|
|
3651
|
-
generation += 1;
|
|
3652
|
-
current = best;
|
|
3653
|
-
currentScore = bestScore;
|
|
3678
|
+
let best = '';
|
|
3679
|
+
let bestScore = Infinity;
|
|
3654
3680
|
|
|
3655
|
-
|
|
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
|
+
}
|
|
3656
3688
|
}
|
|
3657
3689
|
|
|
3658
3690
|
const outList = new ListTerm([
|
|
3659
|
-
|
|
3660
|
-
internLiteral(String(
|
|
3661
|
-
|
|
3662
|
-
internLiteral(String(seed0)),
|
|
3691
|
+
makeStringLiteral(best),
|
|
3692
|
+
internLiteral(String(bestScore)),
|
|
3693
|
+
internLiteral(state.toString()),
|
|
3663
3694
|
]);
|
|
3664
3695
|
|
|
3665
3696
|
const s2 = unifyTerm(g.o, outList, subst);
|
|
@@ -3686,11 +3717,6 @@ function isBuiltinPred(p) {
|
|
|
3686
3717
|
return true;
|
|
3687
3718
|
}
|
|
3688
3719
|
|
|
3689
|
-
// Eyeling extension: GA demo builtins
|
|
3690
|
-
if (v === 'urn:eyeling:ga:solveString') {
|
|
3691
|
-
return true;
|
|
3692
|
-
}
|
|
3693
|
-
|
|
3694
3720
|
return (
|
|
3695
3721
|
v.startsWith(CRYPTO_NS) ||
|
|
3696
3722
|
v.startsWith(MATH_NS) ||
|
package/lib/builtins.js
CHANGED
|
@@ -52,6 +52,11 @@ const __parseNumericInfoCache = new Map(); // lit string -> info|null
|
|
|
52
52
|
// Caching them retains giant strings/BigInts in global Maps and can cause OOM.
|
|
53
53
|
const MAX_NUMERIC_CACHE_KEY_LEN = 1024;
|
|
54
54
|
|
|
55
|
+
// Safety cap for BigInt exponentiation results.
|
|
56
|
+
// Prevents accidental creation of enormous integers that would OOM the process.
|
|
57
|
+
// (Ackermann(4,2) is ~65k bits, so well below this.)
|
|
58
|
+
const MAX_BIGINT_POW_RESULT_BITS = 2_000_000n;
|
|
59
|
+
|
|
55
60
|
function __useNumericCacheKey(key) {
|
|
56
61
|
return typeof key === 'string' && key.length <= MAX_NUMERIC_CACHE_KEY_LEN;
|
|
57
62
|
}
|
|
@@ -591,6 +596,31 @@ function pow10n(k) {
|
|
|
591
596
|
return 10n ** BigInt(k);
|
|
592
597
|
}
|
|
593
598
|
|
|
599
|
+
function absBigInt(x) {
|
|
600
|
+
return x < 0n ? -x : x;
|
|
601
|
+
}
|
|
602
|
+
|
|
603
|
+
function bigintBitLength(x) {
|
|
604
|
+
// Returns the bit length of |x| as a BigInt (0 for 0).
|
|
605
|
+
const a = absBigInt(x);
|
|
606
|
+
if (a === 0n) return 0n;
|
|
607
|
+
// toString(2) is fine here: we only use this as a conservative size guard.
|
|
608
|
+
return BigInt(a.toString(2).length);
|
|
609
|
+
}
|
|
610
|
+
|
|
611
|
+
function estimatePowResultBits(base, exp) {
|
|
612
|
+
// Conservative estimate of bit length for |base| ** exp (exp >= 0).
|
|
613
|
+
// For |base| in {0,1} this is tiny; otherwise ~ exp * log2(|base|).
|
|
614
|
+
if (exp === 0n) return 1n;
|
|
615
|
+
const a = absBigInt(base);
|
|
616
|
+
if (a === 0n) return 1n; // 0**k (k>0) => 0
|
|
617
|
+
if (a === 1n) return 1n;
|
|
618
|
+
const bl = bigintBitLength(a);
|
|
619
|
+
// If bl is the bit length, then 2^(bl-1) <= a < 2^bl.
|
|
620
|
+
// So a^exp has < bl*exp bits and >= (bl-1)*exp+1 bits.
|
|
621
|
+
return (bl - 1n) * exp + 1n;
|
|
622
|
+
}
|
|
623
|
+
|
|
594
624
|
// ===========================================================================
|
|
595
625
|
// Time & duration builtin helpers
|
|
596
626
|
// ===========================================================================
|
|
@@ -1750,50 +1780,87 @@ function evalBuiltin(goal, subst, facts, backRules, depth, varGen, maxResults) {
|
|
|
1750
1780
|
}
|
|
1751
1781
|
|
|
1752
1782
|
// math:exponentiation
|
|
1753
|
-
|
|
1754
|
-
|
|
1755
|
-
|
|
1756
|
-
|
|
1783
|
+
// math:bigExponentiation (exact-integer BigInt-only variant)
|
|
1784
|
+
if (pv === MATH_NS + 'exponentiation' || pv === MATH_NS + 'bigExponentiation') {
|
|
1785
|
+
const onlyBigInt = pv === MATH_NS + 'bigExponentiation';
|
|
1786
|
+
|
|
1787
|
+
if (!(g.s instanceof ListTerm) || g.s.elems.length !== 2) return [];
|
|
1788
|
+
const baseTerm = g.s.elems[0];
|
|
1789
|
+
const expTerm = g.s.elems[1];
|
|
1790
|
+
|
|
1791
|
+
// 1) Exact integer mode (BigInt): (base exponent) -> result
|
|
1792
|
+
// This avoids huge intermediate derivations for things like Ackermann(4,2).
|
|
1793
|
+
const baseI = parseIntLiteral(baseTerm);
|
|
1794
|
+
const expI = parseIntLiteral(expTerm);
|
|
1795
|
+
if (baseI !== null && expI !== null && expI >= 0n) {
|
|
1796
|
+
// Size guard: refuse powers that would almost certainly OOM.
|
|
1797
|
+
const estBits = estimatePowResultBits(baseI, expI);
|
|
1798
|
+
if (estBits > MAX_BIGINT_POW_RESULT_BITS) return [];
|
|
1799
|
+
|
|
1800
|
+
let out;
|
|
1801
|
+
try {
|
|
1802
|
+
out = baseI ** expI;
|
|
1803
|
+
} catch {
|
|
1804
|
+
return [];
|
|
1805
|
+
}
|
|
1806
|
+
|
|
1807
|
+
const lit = makeNumericOutputLiteral(out, XSD_INTEGER_DT);
|
|
1808
|
+
|
|
1809
|
+
if (g.o instanceof Var) {
|
|
1810
|
+
const s2 = { ...subst };
|
|
1811
|
+
s2[g.o.name] = lit;
|
|
1812
|
+
return [s2];
|
|
1813
|
+
}
|
|
1814
|
+
if (g.o instanceof Blank) return [{ ...subst }];
|
|
1757
1815
|
|
|
1758
|
-
const
|
|
1759
|
-
|
|
1760
|
-
if (a !== null) b = parseNum(expTerm);
|
|
1816
|
+
const oi = parseIntLiteral(g.o);
|
|
1817
|
+
if (oi !== null && oi === out) return [{ ...subst }];
|
|
1761
1818
|
|
|
1762
|
-
|
|
1763
|
-
|
|
1764
|
-
|
|
1765
|
-
if (!Number.isFinite(cVal)) return [];
|
|
1819
|
+
const s2 = unifyTerm(g.o, lit, subst);
|
|
1820
|
+
return s2 !== null ? [s2] : [];
|
|
1821
|
+
}
|
|
1766
1822
|
|
|
1767
|
-
|
|
1768
|
-
|
|
1769
|
-
const lit = makeNumericOutputLiteral(cVal, dtOut);
|
|
1823
|
+
// bigExponentiation is intentionally strict.
|
|
1824
|
+
if (onlyBigInt) return [];
|
|
1770
1825
|
|
|
1771
|
-
|
|
1772
|
-
|
|
1773
|
-
|
|
1774
|
-
|
|
1775
|
-
|
|
1776
|
-
|
|
1777
|
-
|
|
1826
|
+
// 2) Numeric mode (Number): forward + limited inverse
|
|
1827
|
+
const a = parseNum(baseTerm);
|
|
1828
|
+
const b = a !== null ? parseNum(expTerm) : null;
|
|
1829
|
+
|
|
1830
|
+
// Forward
|
|
1831
|
+
if (a !== null && b !== null) {
|
|
1832
|
+
const cVal = a ** b;
|
|
1833
|
+
if (!Number.isFinite(cVal)) return [];
|
|
1834
|
+
|
|
1835
|
+
let dtOut = commonNumericDatatype([baseTerm, expTerm], g.o);
|
|
1836
|
+
if (dtOut === XSD_INTEGER_DT && !Number.isInteger(cVal)) dtOut = XSD_DECIMAL_DT;
|
|
1837
|
+
const lit = makeNumericOutputLiteral(cVal, dtOut);
|
|
1838
|
+
|
|
1839
|
+
if (g.o instanceof Var) {
|
|
1840
|
+
const s2 = { ...subst };
|
|
1841
|
+
s2[g.o.name] = lit;
|
|
1842
|
+
return [s2];
|
|
1778
1843
|
}
|
|
1844
|
+
if (g.o instanceof Blank) return [{ ...subst }];
|
|
1845
|
+
if (numEqualTerm(g.o, cVal)) return [{ ...subst }];
|
|
1846
|
+
}
|
|
1779
1847
|
|
|
1780
|
-
|
|
1781
|
-
|
|
1782
|
-
|
|
1783
|
-
|
|
1784
|
-
|
|
1785
|
-
|
|
1848
|
+
// Inverse: solve exponent using logs (Number mode only)
|
|
1849
|
+
const c = parseNum(g.o);
|
|
1850
|
+
if (a !== null && expTerm instanceof Var && c !== null) {
|
|
1851
|
+
if (a > 0.0 && a !== 1.0 && c > 0.0) {
|
|
1852
|
+
const bVal = Math.log(c) / Math.log(a);
|
|
1853
|
+
if (!Number.isFinite(bVal)) return [];
|
|
1786
1854
|
|
|
1787
|
-
|
|
1788
|
-
|
|
1855
|
+
let dtB = commonNumericDatatype([baseTerm, g.o], expTerm);
|
|
1856
|
+
if (dtB === XSD_INTEGER_DT && !Number.isInteger(bVal)) dtB = XSD_DECIMAL_DT;
|
|
1789
1857
|
|
|
1790
|
-
|
|
1791
|
-
|
|
1792
|
-
|
|
1793
|
-
}
|
|
1858
|
+
const s2 = { ...subst };
|
|
1859
|
+
s2[expTerm.name] = makeNumericOutputLiteral(bVal, dtB);
|
|
1860
|
+
return [s2];
|
|
1794
1861
|
}
|
|
1795
|
-
return [];
|
|
1796
1862
|
}
|
|
1863
|
+
return [];
|
|
1797
1864
|
}
|
|
1798
1865
|
|
|
1799
1866
|
// math:absoluteValue
|
|
@@ -3535,34 +3602,32 @@ function evalBuiltin(goal, subst, facts, backRules, depth, varGen, maxResults) {
|
|
|
3535
3602
|
return s2 !== null ? [s2] : [];
|
|
3536
3603
|
}
|
|
3537
3604
|
|
|
3538
|
-
//
|
|
3539
|
-
//
|
|
3540
|
-
//
|
|
3541
|
-
|
|
3542
|
-
//
|
|
3543
|
-
//
|
|
3544
|
-
//
|
|
3545
|
-
|
|
3546
|
-
|
|
3547
|
-
|
|
3548
|
-
|
|
3549
|
-
|
|
3550
|
-
const samplesNum = parseNum(g.s.elems[
|
|
3551
|
-
const
|
|
3552
|
-
const
|
|
3553
|
-
const
|
|
3554
|
-
|
|
3555
|
-
|
|
3556
|
-
if (
|
|
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 [];
|
|
3557
3626
|
|
|
3558
|
-
const mutProb = Math.max(0, Math.trunc(mutProbNum));
|
|
3559
3627
|
const samples = Math.max(1, Math.trunc(samplesNum));
|
|
3628
|
+
const mutProb = Math.max(0, Math.trunc(mutProbNum));
|
|
3560
3629
|
const seed0 = Math.trunc(seedNum);
|
|
3561
3630
|
|
|
3562
|
-
const traceEvery = Math.max(0, Math.trunc(traceEveryNum));
|
|
3563
|
-
const maxGenerations = Math.max(0, Math.trunc(maxGenNum));
|
|
3564
|
-
|
|
3565
|
-
// Deterministic 31-bit LCG using BigInt arithmetic (matches the N3 version)
|
|
3566
3631
|
let state = BigInt(seed0);
|
|
3567
3632
|
const MOD = 2147483648n; // 2^31
|
|
3568
3633
|
const A = 1103515245n;
|
|
@@ -3582,12 +3647,6 @@ function evalBuiltin(goal, subst, facts, backRules, depth, varGen, maxResults) {
|
|
|
3582
3647
|
return p === 0 ? ' ' : String.fromCharCode(64 + p);
|
|
3583
3648
|
}
|
|
3584
3649
|
|
|
3585
|
-
function randomText(len) {
|
|
3586
|
-
let out = '';
|
|
3587
|
-
for (let i = 0; i < len; i++) out += randomAlpha();
|
|
3588
|
-
return out;
|
|
3589
|
-
}
|
|
3590
|
-
|
|
3591
3650
|
function mutate(str) {
|
|
3592
3651
|
let out = '';
|
|
3593
3652
|
for (let i = 0; i < str.length; i++) {
|
|
@@ -3604,50 +3663,22 @@ function evalBuiltin(goal, subst, facts, backRules, depth, varGen, maxResults) {
|
|
|
3604
3663
|
return diffs;
|
|
3605
3664
|
}
|
|
3606
3665
|
|
|
3607
|
-
|
|
3608
|
-
|
|
3609
|
-
const genLit = internLiteral(String(gen));
|
|
3610
|
-
const scLit = internLiteral(String(sc));
|
|
3611
|
-
const valLit = makeStringLiteral(val);
|
|
3612
|
-
const obj = new ListTerm([scLit, valLit]);
|
|
3613
|
-
const xStr = termToN3(genLit, pref);
|
|
3614
|
-
const yStr = termToN3(obj, pref);
|
|
3615
|
-
trace.writeTraceLine(`${xStr} TRACE ${yStr}`);
|
|
3616
|
-
}
|
|
3617
|
-
|
|
3618
|
-
let generation = 0;
|
|
3619
|
-
let current = randomText(target.length);
|
|
3620
|
-
let currentScore = score(current);
|
|
3621
|
-
|
|
3622
|
-
if (traceEvery > 0 && generation % traceEvery === 0) doTrace(generation, currentScore, current);
|
|
3623
|
-
|
|
3624
|
-
while (currentScore !== 0) {
|
|
3625
|
-
if (maxGenerations > 0 && generation >= maxGenerations) break;
|
|
3626
|
-
|
|
3627
|
-
let best = '';
|
|
3628
|
-
let bestScore = Infinity;
|
|
3629
|
-
|
|
3630
|
-
for (let i = 0; i < samples; i++) {
|
|
3631
|
-
const cand = mutate(current);
|
|
3632
|
-
const candScore = score(cand);
|
|
3633
|
-
if (candScore < bestScore) {
|
|
3634
|
-
best = cand;
|
|
3635
|
-
bestScore = candScore;
|
|
3636
|
-
}
|
|
3637
|
-
}
|
|
3638
|
-
|
|
3639
|
-
generation += 1;
|
|
3640
|
-
current = best;
|
|
3641
|
-
currentScore = bestScore;
|
|
3666
|
+
let best = '';
|
|
3667
|
+
let bestScore = Infinity;
|
|
3642
3668
|
|
|
3643
|
-
|
|
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
|
+
}
|
|
3644
3676
|
}
|
|
3645
3677
|
|
|
3646
3678
|
const outList = new ListTerm([
|
|
3647
|
-
|
|
3648
|
-
internLiteral(String(
|
|
3649
|
-
|
|
3650
|
-
internLiteral(String(seed0)),
|
|
3679
|
+
makeStringLiteral(best),
|
|
3680
|
+
internLiteral(String(bestScore)),
|
|
3681
|
+
internLiteral(state.toString()),
|
|
3651
3682
|
]);
|
|
3652
3683
|
|
|
3653
3684
|
const s2 = unifyTerm(g.o, outList, subst);
|
|
@@ -3674,11 +3705,6 @@ function isBuiltinPred(p) {
|
|
|
3674
3705
|
return true;
|
|
3675
3706
|
}
|
|
3676
3707
|
|
|
3677
|
-
// Eyeling extension: GA demo builtins
|
|
3678
|
-
if (v === 'urn:eyeling:ga:solveString') {
|
|
3679
|
-
return true;
|
|
3680
|
-
}
|
|
3681
|
-
|
|
3682
3708
|
return (
|
|
3683
3709
|
v.startsWith(CRYPTO_NS) ||
|
|
3684
3710
|
v.startsWith(MATH_NS) ||
|