eyelang 1.1.15 → 1.1.17
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/docs/guide.md +15 -2
- package/docs/language-reference.md +1 -1
- package/examples/binomial-vandermonde.pl +45 -0
- package/examples/catalan-convolution.pl +33 -0
- package/examples/chart-parser.pl +59 -0
- package/examples/continued-fraction-sqrt2.pl +30 -0
- package/examples/critical-path-schedule.pl +77 -0
- package/examples/integer-partitions.pl +30 -0
- package/examples/job-shop-scheduling.pl +44 -0
- package/examples/knapsack-optimization.pl +40 -0
- package/examples/matrix-chain-order.pl +72 -0
- package/examples/missionaries-cannibals.pl +47 -0
- package/examples/modular-exponentiation.pl +31 -0
- package/examples/n-queens-8.pl +31 -0
- package/examples/output/binomial-vandermonde.pl +4 -0
- package/examples/output/catalan-convolution.pl +4 -0
- package/examples/output/chart-parser.pl +6 -0
- package/examples/output/continued-fraction-sqrt2.pl +4 -0
- package/examples/output/critical-path-schedule.pl +19 -0
- package/examples/output/integer-partitions.pl +4 -0
- package/examples/output/job-shop-scheduling.pl +3 -0
- package/examples/output/knapsack-optimization.pl +4 -0
- package/examples/output/matrix-chain-order.pl +4 -0
- package/examples/output/missionaries-cannibals.pl +3 -0
- package/examples/output/modular-exponentiation.pl +4 -0
- package/examples/output/n-queens-8.pl +1 -0
- package/examples/output/pell-equation.pl +4 -0
- package/examples/output/send-more-money.pl +3 -0
- package/examples/output/stable-marriage.pl +2 -0
- package/examples/output/stirling-bell-numbers.pl +4 -0
- package/examples/output/sudoku-4x4.pl +2 -0
- package/examples/output/totient-summatory.pl +4 -0
- package/examples/output/weighted-interval-scheduling.pl +5 -0
- package/examples/pell-equation.pl +29 -0
- package/examples/send-more-money.pl +66 -0
- package/examples/stable-marriage.pl +86 -0
- package/examples/stirling-bell-numbers.pl +26 -0
- package/examples/sudoku-4x4.pl +48 -0
- package/examples/totient-summatory.pl +29 -0
- package/examples/weighted-interval-scheduling.pl +76 -0
- package/package.json +1 -1
- package/playground.html +14 -0
- package/test/run-regression.mjs +29 -0
package/docs/guide.md
CHANGED
|
@@ -197,7 +197,7 @@ The default output is then:
|
|
|
197
197
|
answer(case1, accepted).
|
|
198
198
|
```
|
|
199
199
|
|
|
200
|
-
`materialize/2` is a declaration, not a logical rule to prove. It affects which predicates the CLI prints, not the meaning of the rules themselves.
|
|
200
|
+
`materialize/2` is a declaration, not a logical rule to prove. It affects which predicates the CLI prints, not the meaning of the rules themselves. Materialized output facts are not inserted back into the running program for later goals; if later output predicates reuse the same derived helper relation, eyelang proves it again unless that helper is declared with `memoize/2`. Source facts are indexed and reused normally, and memoized solved goals are reused inside the same solver run.
|
|
201
201
|
|
|
202
202
|
## Writing programs
|
|
203
203
|
|
|
@@ -321,6 +321,7 @@ Each example has a checked golden output in `examples/output`.
|
|
|
321
321
|
| [`bayes-diagnosis.pl`](../examples/bayes-diagnosis.pl) | Computes scaled Bayesian diagnosis posteriors. | [`output/bayes-diagnosis.pl`](../examples/output/bayes-diagnosis.pl) |
|
|
322
322
|
| [`bayes-therapy.pl`](../examples/bayes-therapy.pl) | Ranks therapies using Bayesian disease likelihoods. | [`output/bayes-therapy.pl`](../examples/output/bayes-therapy.pl) |
|
|
323
323
|
| [`beam-deflection.pl`](../examples/beam-deflection.pl) | Computes cantilever beam deflection. | [`output/beam-deflection.pl`](../examples/output/beam-deflection.pl) |
|
|
324
|
+
| [`binomial-vandermonde.pl`](../examples/binomial-vandermonde.pl) | Computes binomial coefficients and checks Vandermonde's identity. | [`output/binomial-vandermonde.pl`](../examples/output/binomial-vandermonde.pl) |
|
|
324
325
|
| [`blocks-world-planning.pl`](../examples/blocks-world-planning.pl) | Searches a finite blocks-world plan. | [`output/blocks-world-planning.pl`](../examples/output/blocks-world-planning.pl) |
|
|
325
326
|
| [`bmi.pl`](../examples/bmi.pl) | Normalizes BMI inputs and classifies weight. | [`output/bmi.pl`](../examples/output/bmi.pl) |
|
|
326
327
|
| [`braking-safety-worlds.pl`](../examples/braking-safety-worlds.pl) | Classifies braking safety under alternative worlds. | [`output/braking-safety-worlds.pl`](../examples/output/braking-safety-worlds.pl) |
|
|
@@ -328,6 +329,8 @@ Each example has a checked golden output in `examples/output`.
|
|
|
328
329
|
| [`cache-performance.pl`](../examples/cache-performance.pl) | Summarizes cache latency performance. | [`output/cache-performance.pl`](../examples/output/cache-performance.pl) |
|
|
329
330
|
| [`canary-release.pl`](../examples/canary-release.pl) | Decides canary rollout or rollback. | [`output/canary-release.pl`](../examples/output/canary-release.pl) |
|
|
330
331
|
| [`cat-koko.pl`](../examples/cat-koko.pl) | Demonstrates named existential witnesses from a Cat Koko rule pattern. | [`output/cat-koko.pl`](../examples/output/cat-koko.pl) |
|
|
332
|
+
| [`catalan-convolution.pl`](../examples/catalan-convolution.pl) | Computes Catalan numbers by memoized convolution. | [`output/catalan-convolution.pl`](../examples/output/catalan-convolution.pl) |
|
|
333
|
+
| [`chart-parser.pl`](../examples/chart-parser.pl) | Parses small sentences with a memoized chart parser. | [`output/chart-parser.pl`](../examples/output/chart-parser.pl) |
|
|
331
334
|
| [`clinical-trial-screening.pl`](../examples/clinical-trial-screening.pl) | Screens candidates for a trial. | [`output/clinical-trial-screening.pl`](../examples/output/clinical-trial-screening.pl) |
|
|
332
335
|
| [`collatz-1000.pl`](../examples/collatz-1000.pl) | Materializes Collatz trajectories for starts 1000 down to 1. | [`output/collatz-1000.pl`](../examples/output/collatz-1000.pl) |
|
|
333
336
|
| [`combinatorics-findall-sort.pl`](../examples/combinatorics-findall-sort.pl) | Collects and sorts finite combinations. | [`output/combinatorics-findall-sort.pl`](../examples/output/combinatorics-findall-sort.pl) |
|
|
@@ -336,7 +339,9 @@ Each example has a checked golden output in `examples/output`.
|
|
|
336
339
|
| [`composition-of-injective-functions-is-injective.pl`](../examples/composition-of-injective-functions-is-injective.pl) | Encodes composition and injectivity of finite functions. | [`output/composition-of-injective-functions-is-injective.pl`](../examples/output/composition-of-injective-functions-is-injective.pl) |
|
|
337
340
|
| [`context-association.pl`](../examples/context-association.pl) | Associates named contexts with their contents. | [`output/context-association.pl`](../examples/output/context-association.pl) |
|
|
338
341
|
| [`context-schema-audit.pl`](../examples/context-schema-audit.pl) | Audits mixed-arity context members with `holds/3`. | [`output/context-schema-audit.pl`](../examples/output/context-schema-audit.pl) |
|
|
342
|
+
| [`continued-fraction-sqrt2.pl`](../examples/continued-fraction-sqrt2.pl) | Computes sqrt(2) continued-fraction convergents and Pell errors. | [`output/continued-fraction-sqrt2.pl`](../examples/output/continued-fraction-sqrt2.pl) |
|
|
339
343
|
| [`control-system.pl`](../examples/control-system.pl) | Evaluates control-system measurements and targets. | [`output/control-system.pl`](../examples/output/control-system.pl) |
|
|
344
|
+
| [`critical-path-schedule.pl`](../examples/critical-path-schedule.pl) | Computes earliest starts and the critical path for a project network. | [`output/critical-path-schedule.pl`](../examples/output/critical-path-schedule.pl) |
|
|
340
345
|
| [`cyclic-path.pl`](../examples/cyclic-path.pl) | Computes paths in a cyclic graph. | [`output/cyclic-path.pl`](../examples/output/cyclic-path.pl) |
|
|
341
346
|
| [`d3-group.pl`](../examples/d3-group.pl) | Enumerates subgroups of the D3 group. | [`output/d3-group.pl`](../examples/output/d3-group.pl) |
|
|
342
347
|
| [`dairy-energy-balance.pl`](../examples/dairy-energy-balance.pl) | Classifies dairy cow energy balance. | [`output/dairy-energy-balance.pl`](../examples/output/dairy-energy-balance.pl) |
|
|
@@ -391,6 +396,7 @@ Each example has a checked golden output in `examples/output`.
|
|
|
391
396
|
| [`heron-theorem.pl`](../examples/heron-theorem.pl) | Computes triangle area by Heron's theorem. | [`output/heron-theorem.pl`](../examples/output/heron-theorem.pl) |
|
|
392
397
|
| [`ideal-gas-law.pl`](../examples/ideal-gas-law.pl) | Applies the ideal gas law. | [`output/ideal-gas-law.pl`](../examples/output/ideal-gas-law.pl) |
|
|
393
398
|
| [`illegitimate-reasoning.pl`](../examples/illegitimate-reasoning.pl) | Detects suspect reasoning patterns. | [`output/illegitimate-reasoning.pl`](../examples/output/illegitimate-reasoning.pl) |
|
|
399
|
+
| [`integer-partitions.pl`](../examples/integer-partitions.pl) | Counts integer partitions with memoized dynamic programming. | [`output/integer-partitions.pl`](../examples/output/integer-partitions.pl) |
|
|
394
400
|
| [`job-shop-scheduling.pl`](../examples/job-shop-scheduling.pl) | Searches a small job-shop schedule and minimizes makespan. | [`output/job-shop-scheduling.pl`](../examples/output/job-shop-scheduling.pl) |
|
|
395
401
|
| [`knapsack-optimization.pl`](../examples/knapsack-optimization.pl) | Optimizes a finite 0/1 knapsack pack with aggregation. | [`output/knapsack-optimization.pl`](../examples/output/knapsack-optimization.pl) |
|
|
396
402
|
| [`knowledge-engineering-alignment-flow.pl`](../examples/knowledge-engineering-alignment-flow.pl) | Specializes reusable alignment rules into a target-shaped flow view. | [`output/knowledge-engineering-alignment-flow.pl`](../examples/output/knowledge-engineering-alignment-flow.pl) |
|
|
@@ -399,7 +405,10 @@ Each example has a checked golden output in `examples/output`.
|
|
|
399
405
|
| [`list-collection.pl`](../examples/list-collection.pl) | Demonstrates list and collection built-ins. | [`output/list-collection.pl`](../examples/output/list-collection.pl) |
|
|
400
406
|
| [`lldm.pl`](../examples/lldm.pl) | Calculates leg-length discrepancy measurements. | [`output/lldm.pl`](../examples/output/lldm.pl) |
|
|
401
407
|
| [`manufacturing-quality-control.pl`](../examples/manufacturing-quality-control.pl) | Evaluates process capability and quality. | [`output/manufacturing-quality-control.pl`](../examples/output/manufacturing-quality-control.pl) |
|
|
408
|
+
| [`matrix-chain-order.pl`](../examples/matrix-chain-order.pl) | Finds an optimal matrix-chain multiplication order. | [`output/matrix-chain-order.pl`](../examples/output/matrix-chain-order.pl) |
|
|
402
409
|
| [`microgrid-dispatch.pl`](../examples/microgrid-dispatch.pl) | Plans microgrid dispatch and reserve. | [`output/microgrid-dispatch.pl`](../examples/output/microgrid-dispatch.pl) |
|
|
410
|
+
| [`missionaries-cannibals.pl`](../examples/missionaries-cannibals.pl) | Solves the missionaries-and-cannibals river crossing puzzle. | [`output/missionaries-cannibals.pl`](../examples/output/missionaries-cannibals.pl) |
|
|
411
|
+
| [`modular-exponentiation.pl`](../examples/modular-exponentiation.pl) | Computes modular powers by repeated squaring. | [`output/modular-exponentiation.pl`](../examples/output/modular-exponentiation.pl) |
|
|
403
412
|
| [`monkey-bananas.pl`](../examples/monkey-bananas.pl) | Solves the monkey-and-bananas puzzle. | [`output/monkey-bananas.pl`](../examples/output/monkey-bananas.pl) |
|
|
404
413
|
| [`n-queens-8.pl`](../examples/n-queens-8.pl) | Solves the 8-queens search problem with diagonal constraints. | [`output/n-queens-8.pl`](../examples/output/n-queens-8.pl) |
|
|
405
414
|
| [`network-sla.pl`](../examples/network-sla.pl) | Checks network path SLA compliance. | [`output/network-sla.pl`](../examples/output/network-sla.pl) |
|
|
@@ -413,6 +422,7 @@ Each example has a checked golden output in `examples/output`.
|
|
|
413
422
|
| [`path-discovery.pl`](../examples/path-discovery.pl) | Discovers bounded air-route paths. | [`output/path-discovery.pl`](../examples/output/path-discovery.pl) |
|
|
414
423
|
| [`peano-arithmetic.pl`](../examples/peano-arithmetic.pl) | Computes Peano addition, multiplication, and factorial. | [`output/peano-arithmetic.pl`](../examples/output/peano-arithmetic.pl) |
|
|
415
424
|
| [`peasant.pl`](../examples/peasant.pl) | Performs peasant multiplication and exponentiation. | [`output/peasant.pl`](../examples/output/peasant.pl) |
|
|
425
|
+
| [`pell-equation.pl`](../examples/pell-equation.pl) | Generates Pell-equation solutions by recurrence. | [`output/pell-equation.pl`](../examples/output/pell-equation.pl) |
|
|
416
426
|
| [`pendulum-period.pl`](../examples/pendulum-period.pl) | Computes simple pendulum periods. | [`output/pendulum-period.pl`](../examples/output/pendulum-period.pl) |
|
|
417
427
|
| [`polynomial.pl`](../examples/polynomial.pl) | Finds complex integer polynomial roots. | [`output/polynomial.pl`](../examples/output/polynomial.pl) |
|
|
418
428
|
| [`proof-contrapositive.pl`](../examples/proof-contrapositive.pl) | Models proof by contrapositive. | [`output/proof-contrapositive.pl`](../examples/output/proof-contrapositive.pl) |
|
|
@@ -430,17 +440,20 @@ Each example has a checked golden output in `examples/output`.
|
|
|
430
440
|
| [`socrates.pl`](../examples/socrates.pl) | Derives that Socrates is mortal. | [`output/socrates.pl`](../examples/output/socrates.pl) |
|
|
431
441
|
| [`stable-marriage.pl`](../examples/stable-marriage.pl) | Finds stable matchings by excluding blocking pairs. | [`output/stable-marriage.pl`](../examples/output/stable-marriage.pl) |
|
|
432
442
|
| [`statistics-summary.pl`](../examples/statistics-summary.pl) | Computes population statistics for a sample. | [`output/statistics-summary.pl`](../examples/output/statistics-summary.pl) |
|
|
443
|
+
| [`stirling-bell-numbers.pl`](../examples/stirling-bell-numbers.pl) | Computes Stirling numbers and Bell numbers. | [`output/stirling-bell-numbers.pl`](../examples/output/stirling-bell-numbers.pl) |
|
|
444
|
+
| [`sudoku-4x4.pl`](../examples/sudoku-4x4.pl) | Solves a compact 4x4 Sudoku by finite constraint search. | [`output/sudoku-4x4.pl`](../examples/output/sudoku-4x4.pl) |
|
|
433
445
|
| [`superdense-coding.pl`](../examples/superdense-coding.pl) | Models superdense-coding bit transmission. | [`output/superdense-coding.pl`](../examples/output/superdense-coding.pl) |
|
|
434
446
|
| [`term-tools.pl`](../examples/term-tools.pl) | Inspects, builds, renders, and validates terms with reusable term/control builtins. | [`output/term-tools.pl`](../examples/output/term-tools.pl) |
|
|
447
|
+
| [`totient-summatory.pl`](../examples/totient-summatory.pl) | Computes Euler totients and their summatory function. | [`output/totient-summatory.pl`](../examples/output/totient-summatory.pl) |
|
|
435
448
|
| [`trust-flow-provenance-threshold.pl`](../examples/trust-flow-provenance-threshold.pl) | Classifies message trust from provenance confidence scores. | [`output/trust-flow-provenance-threshold.pl`](../examples/output/trust-flow-provenance-threshold.pl) |
|
|
436
449
|
| [`turing.pl`](../examples/turing.pl) | Simulates a binary-increment Turing machine. | [`output/turing.pl`](../examples/output/turing.pl) |
|
|
437
450
|
| [`vector-similarity.pl`](../examples/vector-similarity.pl) | Computes dot product, norm, and cosine similarity. | [`output/vector-similarity.pl`](../examples/output/vector-similarity.pl) |
|
|
438
451
|
| [`vulnerability-impact.pl`](../examples/vulnerability-impact.pl) | Analyzes vulnerable transitive dependencies and urgent patch impact. | [`output/vulnerability-impact.pl`](../examples/output/vulnerability-impact.pl) |
|
|
452
|
+
| [`weighted-interval-scheduling.pl`](../examples/weighted-interval-scheduling.pl) | Selects the best non-overlapping weighted intervals with memoized dynamic programming. | [`output/weighted-interval-scheduling.pl`](../examples/output/weighted-interval-scheduling.pl) |
|
|
439
453
|
| [`witch.pl`](../examples/witch.pl) | Derives the classic “burn the witch” rule chain. | [`output/witch.pl`](../examples/output/witch.pl) |
|
|
440
454
|
| [`wolf-goat-cabbage.pl`](../examples/wolf-goat-cabbage.pl) | Solves the wolf-goat-cabbage river crossing. | [`output/wolf-goat-cabbage.pl`](../examples/output/wolf-goat-cabbage.pl) |
|
|
441
455
|
| [`zebra.pl`](../examples/zebra.pl) | Solves the zebra logic puzzle. | [`output/zebra.pl`](../examples/output/zebra.pl) |
|
|
442
456
|
|
|
443
|
-
|
|
444
457
|
## Golden outputs, tests, and conformance
|
|
445
458
|
|
|
446
459
|
Golden answer outputs live in [`examples/output`](../examples/output). `npm run test:eyelang` covers the eyelang integration check, conformance cases, regression checks, runnable examples, and proof-output examples. A curated proof-output suite for `.pl` examples lives in [`examples/proof`](../examples/proof). Example tests pin `local_time/1` to `2026-05-30` so date-dependent examples stay deterministic. Regenerate them after an intentional output or explanation change:
|
|
@@ -534,7 +534,7 @@ materialize(status, 2).
|
|
|
534
534
|
materialize(reason, 2).
|
|
535
535
|
```
|
|
536
536
|
|
|
537
|
-
`materialize/2` affects host output selection only; it does not change the logical meaning of the program.
|
|
537
|
+
`materialize/2` affects host output selection only; it does not change the logical meaning of the program. Materialized output facts are not asserted as new source facts for subsequent output goals. A host MAY solve several materialized predicates in one solver run, and memoized predicate answers MAY be reused within that run, but this reuse is controlled by `memoize/2`, not by materialization.
|
|
538
538
|
|
|
539
539
|
## 12. Eyelang Sockets
|
|
540
540
|
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
% Binomial coefficients and Vandermonde's identity.
|
|
2
|
+
% choose_step/5 uses the multiplicative recurrence
|
|
3
|
+
% C(N, I+1) = C(N, I) * (N-I) / (I+1)
|
|
4
|
+
% and is memoized because row sums and identities reuse prefixes.
|
|
5
|
+
materialize(binomial_answer, 2).
|
|
6
|
+
|
|
7
|
+
memoize(choose_step, 5).
|
|
8
|
+
|
|
9
|
+
choose(N, K, C) :-
|
|
10
|
+
ge(K, 0),
|
|
11
|
+
le(K, N),
|
|
12
|
+
choose_step(N, K, 0, 1, C).
|
|
13
|
+
|
|
14
|
+
choose_step(_N, K, K, Acc, Acc).
|
|
15
|
+
choose_step(N, K, I, Acc, C) :-
|
|
16
|
+
lt(I, K),
|
|
17
|
+
add(I, 1, I1),
|
|
18
|
+
sub(N, I, Factor),
|
|
19
|
+
mul(Acc, Factor, Numerator),
|
|
20
|
+
div(Numerator, I1, NextAcc),
|
|
21
|
+
choose_step(N, K, I1, NextAcc, C).
|
|
22
|
+
|
|
23
|
+
symmetric(N, K) :-
|
|
24
|
+
choose(N, K, C),
|
|
25
|
+
sub(N, K, OtherK),
|
|
26
|
+
choose(N, OtherK, C).
|
|
27
|
+
|
|
28
|
+
vandermonde_sum(N, M, R, Sum) :-
|
|
29
|
+
sumall(Product,
|
|
30
|
+
(between(0, R, K),
|
|
31
|
+
sub(R, K, RK),
|
|
32
|
+
choose(N, K, A),
|
|
33
|
+
choose(M, RK, B),
|
|
34
|
+
mul(A, B, Product)),
|
|
35
|
+
Sum).
|
|
36
|
+
|
|
37
|
+
vandermonde(N, M, R, Sum) :-
|
|
38
|
+
add(N, M, TotalN),
|
|
39
|
+
choose(TotalN, R, Sum),
|
|
40
|
+
vandermonde_sum(N, M, R, Sum).
|
|
41
|
+
|
|
42
|
+
binomial_answer(choose_24_12, C) :- choose(24, 12, C).
|
|
43
|
+
binomial_answer(symmetry_24_7, true) :- symmetric(24, 7).
|
|
44
|
+
binomial_answer(vandermonde_12_10_8, Sum) :- vandermonde(12, 10, 8, Sum).
|
|
45
|
+
binomial_answer(row_12_sum, Sum) :- sumall(C, (between(0, 12, K), choose(12, K, C)), Sum).
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
% Catalan numbers by memoized convolution.
|
|
2
|
+
% catalan/2 counts binary tree shapes, parenthesizations, and polygon
|
|
3
|
+
% triangulations with the usual index shifts.
|
|
4
|
+
materialize(catalan_answer, 2).
|
|
5
|
+
|
|
6
|
+
memoize(catalan, 2).
|
|
7
|
+
|
|
8
|
+
catalan(0, 1).
|
|
9
|
+
catalan(N, C) :-
|
|
10
|
+
gt(N, 0),
|
|
11
|
+
sub(N, 1, N1),
|
|
12
|
+
sumall(Product,
|
|
13
|
+
(between(0, N1, I),
|
|
14
|
+
sub(N1, I, J),
|
|
15
|
+
catalan(I, A),
|
|
16
|
+
catalan(J, B),
|
|
17
|
+
mul(A, B, Product)),
|
|
18
|
+
C).
|
|
19
|
+
|
|
20
|
+
polygon_triangulations(Sides, Count) :-
|
|
21
|
+
ge(Sides, 3),
|
|
22
|
+
sub(Sides, 2, N),
|
|
23
|
+
catalan(N, Count).
|
|
24
|
+
|
|
25
|
+
parenthesizations(Factors, Count) :-
|
|
26
|
+
ge(Factors, 1),
|
|
27
|
+
sub(Factors, 1, N),
|
|
28
|
+
catalan(N, Count).
|
|
29
|
+
|
|
30
|
+
catalan_answer(catalan_12, C) :- catalan(12, C).
|
|
31
|
+
catalan_answer(triangulations_14_gon, Count) :- polygon_triangulations(14, Count).
|
|
32
|
+
catalan_answer(parenthesizations_13_factors, Count) :- parenthesizations(13, Count).
|
|
33
|
+
catalan_answer(first_ten_sum, Sum) :- sumall(C, (between(0, 9, N), catalan(N, C)), Sum).
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
% A tiny memoized chart parser for a context-free grammar.
|
|
2
|
+
% span/4 is the dynamic-programming chart relation: sentence, category,
|
|
3
|
+
% start index, and end index.
|
|
4
|
+
materialize(chart_parser_answer, 2).
|
|
5
|
+
|
|
6
|
+
memoize(span, 4).
|
|
7
|
+
|
|
8
|
+
sentence(command, 5).
|
|
9
|
+
sentence(ambiguous_pp, 8).
|
|
10
|
+
|
|
11
|
+
word(command, 0, the).
|
|
12
|
+
word(command, 1, robot).
|
|
13
|
+
word(command, 2, moves).
|
|
14
|
+
word(command, 3, the).
|
|
15
|
+
word(command, 4, box).
|
|
16
|
+
|
|
17
|
+
word(ambiguous_pp, 0, the).
|
|
18
|
+
word(ambiguous_pp, 1, robot).
|
|
19
|
+
word(ambiguous_pp, 2, sees).
|
|
20
|
+
word(ambiguous_pp, 3, the).
|
|
21
|
+
word(ambiguous_pp, 4, box).
|
|
22
|
+
word(ambiguous_pp, 5, with).
|
|
23
|
+
word(ambiguous_pp, 6, the).
|
|
24
|
+
word(ambiguous_pp, 7, telescope).
|
|
25
|
+
|
|
26
|
+
terminal(det, the).
|
|
27
|
+
terminal(noun, robot).
|
|
28
|
+
terminal(noun, box).
|
|
29
|
+
terminal(noun, telescope).
|
|
30
|
+
terminal(verb, moves).
|
|
31
|
+
terminal(verb, sees).
|
|
32
|
+
terminal(prep, with).
|
|
33
|
+
|
|
34
|
+
rule(s, np, vp).
|
|
35
|
+
rule(np, det, noun).
|
|
36
|
+
rule(np, np, pp).
|
|
37
|
+
rule(vp, verb, np).
|
|
38
|
+
rule(vp, vp, pp).
|
|
39
|
+
rule(pp, prep, np).
|
|
40
|
+
|
|
41
|
+
span(Sentence, Category, Start, End) :-
|
|
42
|
+
word(Sentence, Start, Token),
|
|
43
|
+
terminal(Category, Token),
|
|
44
|
+
add(Start, 1, End).
|
|
45
|
+
span(Sentence, Category, Start, End) :-
|
|
46
|
+
rule(Category, Left, Right),
|
|
47
|
+
span(Sentence, Left, Start, Middle),
|
|
48
|
+
span(Sentence, Right, Middle, End).
|
|
49
|
+
|
|
50
|
+
chart_parser_answer(parsed, Sentence) :-
|
|
51
|
+
sentence(Sentence, Length),
|
|
52
|
+
span(Sentence, s, 0, Length).
|
|
53
|
+
chart_parser_answer(parse_count, count(Sentence, Count)) :-
|
|
54
|
+
sentence(Sentence, Length),
|
|
55
|
+
countall(span(Sentence, s, 0, Length), Count).
|
|
56
|
+
chart_parser_answer(noun_phrase_count, count(Sentence, Count)) :-
|
|
57
|
+
sentence(Sentence, Length),
|
|
58
|
+
countall(span(Sentence, np, _Start, _End), Count),
|
|
59
|
+
gt(Length, 0).
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
% Convergents of sqrt(2) by memoized recurrence.
|
|
2
|
+
% conv(N, P, Q) gives the Nth convergent numerator/denominator for [1;2,2,...].
|
|
3
|
+
materialize(convergent_answer, 2).
|
|
4
|
+
|
|
5
|
+
memoize(conv, 3).
|
|
6
|
+
|
|
7
|
+
conv(0, 1, 1).
|
|
8
|
+
conv(1, 3, 2).
|
|
9
|
+
conv(N, P, Q) :-
|
|
10
|
+
gt(N, 1),
|
|
11
|
+
sub(N, 1, N1),
|
|
12
|
+
sub(N, 2, N2),
|
|
13
|
+
conv(N1, P1, Q1),
|
|
14
|
+
conv(N2, P2, Q2),
|
|
15
|
+
mul(2, P1, TwiceP1),
|
|
16
|
+
add(TwiceP1, P2, P),
|
|
17
|
+
mul(2, Q1, TwiceQ1),
|
|
18
|
+
add(TwiceQ1, Q2, Q).
|
|
19
|
+
|
|
20
|
+
pell_error(N, Error) :-
|
|
21
|
+
conv(N, P, Q),
|
|
22
|
+
mul(P, P, P2),
|
|
23
|
+
mul(Q, Q, Q2),
|
|
24
|
+
mul(2, Q2, TwiceQ2),
|
|
25
|
+
sub(P2, TwiceQ2, Error).
|
|
26
|
+
|
|
27
|
+
convergent_answer(convergent_10, fraction(P, Q)) :- conv(10, P, Q).
|
|
28
|
+
convergent_answer(convergent_15, fraction(P, Q)) :- conv(15, P, Q).
|
|
29
|
+
convergent_answer(pell_error_15, Error) :- pell_error(15, Error).
|
|
30
|
+
convergent_answer(numerator_sum_0_to_10, Sum) :- sumall(P, (between(0, 10, N), conv(N, P, _Q)), Sum).
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
% Critical-path scheduling for a small project network.
|
|
2
|
+
% earliest_start/2 and finish_time/2 are memoized because many schedule and
|
|
3
|
+
% critical-path queries reuse the same predecessor subproblems.
|
|
4
|
+
materialize(critical_path_answer, 2).
|
|
5
|
+
|
|
6
|
+
memoize(earliest_start, 2).
|
|
7
|
+
memoize(finish_time, 2).
|
|
8
|
+
|
|
9
|
+
task(requirements, 2).
|
|
10
|
+
task(architecture, 3).
|
|
11
|
+
task(api_design, 2).
|
|
12
|
+
task(database, 4).
|
|
13
|
+
task(backend, 6).
|
|
14
|
+
task(frontend, 5).
|
|
15
|
+
task(auth, 3).
|
|
16
|
+
task(integration, 4).
|
|
17
|
+
task(security_review, 3).
|
|
18
|
+
task(load_test, 2).
|
|
19
|
+
task(launch, 1).
|
|
20
|
+
|
|
21
|
+
depends(architecture, requirements).
|
|
22
|
+
depends(api_design, requirements).
|
|
23
|
+
depends(database, architecture).
|
|
24
|
+
depends(backend, api_design).
|
|
25
|
+
depends(backend, database).
|
|
26
|
+
depends(frontend, api_design).
|
|
27
|
+
depends(auth, architecture).
|
|
28
|
+
depends(integration, backend).
|
|
29
|
+
depends(integration, frontend).
|
|
30
|
+
depends(integration, auth).
|
|
31
|
+
depends(security_review, integration).
|
|
32
|
+
depends(load_test, integration).
|
|
33
|
+
depends(launch, security_review).
|
|
34
|
+
depends(launch, load_test).
|
|
35
|
+
|
|
36
|
+
earliest_start(Task, 0) :-
|
|
37
|
+
task(Task, _Duration),
|
|
38
|
+
not(depends(Task, _Pred)).
|
|
39
|
+
earliest_start(Task, Start) :-
|
|
40
|
+
depends(Task, _Pred),
|
|
41
|
+
aggregate_max(Finish, Pred,
|
|
42
|
+
(depends(Task, Pred), finish_time(Pred, Finish)),
|
|
43
|
+
Start, _CriticalPred).
|
|
44
|
+
|
|
45
|
+
finish_time(Task, Finish) :-
|
|
46
|
+
task(Task, Duration),
|
|
47
|
+
earliest_start(Task, Start),
|
|
48
|
+
add(Start, Duration, Finish).
|
|
49
|
+
|
|
50
|
+
critical_predecessor(Task, Pred) :-
|
|
51
|
+
depends(Task, _AnyPred),
|
|
52
|
+
aggregate_max(Finish, P,
|
|
53
|
+
(depends(Task, P), finish_time(P, Finish)),
|
|
54
|
+
_BestFinish, Pred).
|
|
55
|
+
|
|
56
|
+
project_finish(Finish) :-
|
|
57
|
+
aggregate_max(FinishTime, Task, finish_time(Task, FinishTime), Finish, _LastTask).
|
|
58
|
+
|
|
59
|
+
final_task(Task) :-
|
|
60
|
+
project_finish(Finish),
|
|
61
|
+
finish_time(Task, Finish).
|
|
62
|
+
|
|
63
|
+
critical_chain(Task, Task).
|
|
64
|
+
critical_chain(Task, Pred) :-
|
|
65
|
+
critical_predecessor(Task, Parent),
|
|
66
|
+
critical_chain(Parent, Pred).
|
|
67
|
+
|
|
68
|
+
critical_task(Task) :-
|
|
69
|
+
final_task(Final),
|
|
70
|
+
critical_chain(Final, Task).
|
|
71
|
+
|
|
72
|
+
critical_path_answer(project_finish, Finish) :- project_finish(Finish).
|
|
73
|
+
critical_path_answer(critical_task, Task) :- critical_task(Task).
|
|
74
|
+
critical_path_answer(schedule, task(Task, Start, Finish)) :-
|
|
75
|
+
task(Task, _Duration),
|
|
76
|
+
earliest_start(Task, Start),
|
|
77
|
+
finish_time(Task, Finish).
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
% Integer partition counts by memoized dynamic programming.
|
|
2
|
+
% partitions(N, K, Count) counts partitions of N using parts no larger than K.
|
|
3
|
+
materialize(partition_answer, 2).
|
|
4
|
+
|
|
5
|
+
memoize(partitions, 3).
|
|
6
|
+
|
|
7
|
+
partitions(0, _K, 1).
|
|
8
|
+
partitions(N, 0, 0) :- gt(N, 0).
|
|
9
|
+
partitions(N, K, Count) :-
|
|
10
|
+
gt(N, 0),
|
|
11
|
+
gt(K, 0),
|
|
12
|
+
gt(K, N),
|
|
13
|
+
sub(K, 1, K1),
|
|
14
|
+
partitions(N, K1, Count).
|
|
15
|
+
partitions(N, K, Count) :-
|
|
16
|
+
gt(N, 0),
|
|
17
|
+
gt(K, 0),
|
|
18
|
+
le(K, N),
|
|
19
|
+
sub(N, K, Remainder),
|
|
20
|
+
partitions(Remainder, K, WithK),
|
|
21
|
+
sub(K, 1, K1),
|
|
22
|
+
partitions(N, K1, WithoutK),
|
|
23
|
+
add(WithK, WithoutK, Count).
|
|
24
|
+
|
|
25
|
+
partition_count(N, Count) :- partitions(N, N, Count).
|
|
26
|
+
|
|
27
|
+
partition_answer(p_12, Count) :- partition_count(12, Count).
|
|
28
|
+
partition_answer(p_15, Count) :- partition_count(15, Count).
|
|
29
|
+
partition_answer(p_16_using_parts_at_most_5, Count) :- partitions(16, 5, Count).
|
|
30
|
+
partition_answer(cumulative_p_1_to_8, Sum) :- sumall(C, (between(1, 8, N), partition_count(N, C)), Sum).
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
% Tiny job-shop scheduling benchmark.
|
|
2
|
+
% Three jobs each need one mill operation and one lathe operation; the solver
|
|
3
|
+
% searches start times and minimizes the makespan.
|
|
4
|
+
materialize(job_shop_answer, 2).
|
|
5
|
+
|
|
6
|
+
nonoverlap(_StartA, EndA, StartB, _EndB) :- le(EndA, StartB).
|
|
7
|
+
nonoverlap(StartA, _EndA, _StartB, EndB) :- le(EndB, StartA).
|
|
8
|
+
|
|
9
|
+
feasible_schedule(Makespan, [
|
|
10
|
+
op(j1_mill, J1MillStart, J1MillEnd),
|
|
11
|
+
op(j1_lathe, J1LatheStart, J1LatheEnd),
|
|
12
|
+
op(j2_lathe, J2LatheStart, J2LatheEnd),
|
|
13
|
+
op(j2_mill, J2MillStart, J2MillEnd),
|
|
14
|
+
op(j3_mill, J3MillStart, J3MillEnd),
|
|
15
|
+
op(j3_lathe, J3LatheStart, J3LatheEnd)
|
|
16
|
+
]) :-
|
|
17
|
+
between(0, 6, J1MillStart), add(J1MillStart, 3, J1MillEnd),
|
|
18
|
+
between(0, 6, J1LatheStart), add(J1LatheStart, 2, J1LatheEnd),
|
|
19
|
+
le(J1MillEnd, J1LatheStart),
|
|
20
|
+
|
|
21
|
+
between(0, 6, J2LatheStart), add(J2LatheStart, 2, J2LatheEnd),
|
|
22
|
+
between(0, 6, J2MillStart), add(J2MillStart, 4, J2MillEnd),
|
|
23
|
+
le(J2LatheEnd, J2MillStart),
|
|
24
|
+
|
|
25
|
+
between(0, 6, J3MillStart), add(J3MillStart, 2, J3MillEnd),
|
|
26
|
+
between(0, 6, J3LatheStart), add(J3LatheStart, 3, J3LatheEnd),
|
|
27
|
+
le(J3MillEnd, J3LatheStart),
|
|
28
|
+
|
|
29
|
+
nonoverlap(J1MillStart, J1MillEnd, J2MillStart, J2MillEnd),
|
|
30
|
+
nonoverlap(J1MillStart, J1MillEnd, J3MillStart, J3MillEnd),
|
|
31
|
+
nonoverlap(J2MillStart, J2MillEnd, J3MillStart, J3MillEnd),
|
|
32
|
+
nonoverlap(J1LatheStart, J1LatheEnd, J2LatheStart, J2LatheEnd),
|
|
33
|
+
nonoverlap(J1LatheStart, J1LatheEnd, J3LatheStart, J3LatheEnd),
|
|
34
|
+
nonoverlap(J2LatheStart, J2LatheEnd, J3LatheStart, J3LatheEnd),
|
|
35
|
+
|
|
36
|
+
max(J1LatheEnd, J2MillEnd, PartialMakespan),
|
|
37
|
+
max(PartialMakespan, J3LatheEnd, Makespan).
|
|
38
|
+
|
|
39
|
+
best_schedule(Makespan, Schedule) :-
|
|
40
|
+
aggregate_min(Makespan, Schedule, feasible_schedule(Makespan, Schedule), Makespan, Schedule).
|
|
41
|
+
|
|
42
|
+
job_shop_answer(best_makespan, Makespan) :- best_schedule(Makespan, _Schedule).
|
|
43
|
+
job_shop_answer(best_schedule, Schedule) :- best_schedule(_Makespan, Schedule).
|
|
44
|
+
job_shop_answer(feasible_schedule_count, Count) :- countall(feasible_schedule(_Makespan, _Schedule), Count).
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
% 0/1 knapsack search with an aggregate maximum over all feasible packs.
|
|
2
|
+
materialize(knapsack_answer, 2).
|
|
3
|
+
|
|
4
|
+
capacity(15).
|
|
5
|
+
items([atlas, battery, camera, drone, emergency_radio, field_laptop, medkit, sensor]).
|
|
6
|
+
|
|
7
|
+
item(atlas, 2, 6).
|
|
8
|
+
item(battery, 4, 10).
|
|
9
|
+
item(camera, 3, 8).
|
|
10
|
+
item(drone, 6, 13).
|
|
11
|
+
item(emergency_radio, 5, 11).
|
|
12
|
+
item(field_laptop, 7, 16).
|
|
13
|
+
item(medkit, 4, 9).
|
|
14
|
+
item(sensor, 2, 7).
|
|
15
|
+
|
|
16
|
+
subset([], []).
|
|
17
|
+
subset([Item|Rest], [Item|Chosen]) :- subset(Rest, Chosen).
|
|
18
|
+
subset([_Item|Rest], Chosen) :- subset(Rest, Chosen).
|
|
19
|
+
|
|
20
|
+
item_weight(Item, Weight) :- item(Item, Weight, _Value).
|
|
21
|
+
item_value(Item, Value) :- item(Item, _Weight, Value).
|
|
22
|
+
|
|
23
|
+
total_weight(Items, Weight) :- findall(W, (member(Item, Items), item_weight(Item, W)), Weights), sum_list(Weights, Weight).
|
|
24
|
+
total_value(Items, Value) :- findall(V, (member(Item, Items), item_value(Item, V)), Values), sum_list(Values, Value).
|
|
25
|
+
|
|
26
|
+
feasible_pack(Pack, Weight, Value) :-
|
|
27
|
+
items(All),
|
|
28
|
+
subset(All, Pack),
|
|
29
|
+
total_weight(Pack, Weight),
|
|
30
|
+
capacity(Capacity),
|
|
31
|
+
le(Weight, Capacity),
|
|
32
|
+
total_value(Pack, Value).
|
|
33
|
+
|
|
34
|
+
best_pack(Pack, Weight, Value) :-
|
|
35
|
+
aggregate_max(Value, pack(Pack, Weight), feasible_pack(Pack, Weight, Value), Value, pack(Pack, Weight)).
|
|
36
|
+
|
|
37
|
+
knapsack_answer(best_pack, Pack) :- best_pack(Pack, _Weight, _Value).
|
|
38
|
+
knapsack_answer(total_weight, Weight) :- best_pack(_Pack, Weight, _Value).
|
|
39
|
+
knapsack_answer(total_value, Value) :- best_pack(_Pack, _Weight, Value).
|
|
40
|
+
knapsack_answer(feasible_pack_count, Count) :- countall(feasible_pack(_Pack, _Weight, _Value), Count).
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
% Matrix-chain multiplication order by memoized interval dynamic programming.
|
|
2
|
+
% cost(I, J, Cost) is the minimum scalar multiplication cost for matrices I..J.
|
|
3
|
+
materialize(matrix_chain_answer, 2).
|
|
4
|
+
|
|
5
|
+
memoize(cost, 3).
|
|
6
|
+
|
|
7
|
+
% Dimensions for the CLRS-style chain: A1 is 30x35, A2 is 35x15, ...
|
|
8
|
+
dim(0, 30).
|
|
9
|
+
dim(1, 35).
|
|
10
|
+
dim(2, 15).
|
|
11
|
+
dim(3, 5).
|
|
12
|
+
dim(4, 10).
|
|
13
|
+
dim(5, 20).
|
|
14
|
+
dim(6, 25).
|
|
15
|
+
|
|
16
|
+
matrix_count(6).
|
|
17
|
+
|
|
18
|
+
cost(I, I, 0) :- matrix_count(N), between(1, N, I).
|
|
19
|
+
cost(I, J, Cost) :-
|
|
20
|
+
lt(I, J),
|
|
21
|
+
aggregate_min(SplitCost, K,
|
|
22
|
+
(between(I, J, K),
|
|
23
|
+
lt(K, J),
|
|
24
|
+
cost(I, K, Left),
|
|
25
|
+
add(K, 1, K1),
|
|
26
|
+
cost(K1, J, Right),
|
|
27
|
+
sub(I, 1, I0),
|
|
28
|
+
dim(I0, Rows),
|
|
29
|
+
dim(K, Shared),
|
|
30
|
+
dim(J, Cols),
|
|
31
|
+
mul(Rows, Shared, First),
|
|
32
|
+
mul(First, Cols, MultCost),
|
|
33
|
+
add(Left, Right, Partial),
|
|
34
|
+
add(Partial, MultCost, SplitCost)),
|
|
35
|
+
Cost, _BestK).
|
|
36
|
+
|
|
37
|
+
best_split(I, J, K) :-
|
|
38
|
+
lt(I, J),
|
|
39
|
+
aggregate_min(SplitCost, K,
|
|
40
|
+
(between(I, J, K),
|
|
41
|
+
lt(K, J),
|
|
42
|
+
cost(I, K, Left),
|
|
43
|
+
add(K, 1, K1),
|
|
44
|
+
cost(K1, J, Right),
|
|
45
|
+
sub(I, 1, I0),
|
|
46
|
+
dim(I0, Rows),
|
|
47
|
+
dim(K, Shared),
|
|
48
|
+
dim(J, Cols),
|
|
49
|
+
mul(Rows, Shared, First),
|
|
50
|
+
mul(First, Cols, MultCost),
|
|
51
|
+
add(Left, Right, Partial),
|
|
52
|
+
add(Partial, MultCost, SplitCost)),
|
|
53
|
+
_Cost, K).
|
|
54
|
+
|
|
55
|
+
parenthesization(I, I, matrix(I)).
|
|
56
|
+
parenthesization(I, J, product(LeftTree, RightTree)) :-
|
|
57
|
+
lt(I, J),
|
|
58
|
+
best_split(I, J, K),
|
|
59
|
+
add(K, 1, K1),
|
|
60
|
+
parenthesization(I, K, LeftTree),
|
|
61
|
+
parenthesization(K1, J, RightTree).
|
|
62
|
+
|
|
63
|
+
matrix_chain_answer(min_cost, Cost) :- cost(1, 6, Cost).
|
|
64
|
+
matrix_chain_answer(best_split_1_6, K) :- best_split(1, 6, K).
|
|
65
|
+
matrix_chain_answer(best_order, Tree) :- parenthesization(1, 6, Tree).
|
|
66
|
+
subproblem(I, J, Cost) :-
|
|
67
|
+
matrix_count(N),
|
|
68
|
+
between(1, N, I),
|
|
69
|
+
between(I, N, J),
|
|
70
|
+
cost(I, J, Cost).
|
|
71
|
+
|
|
72
|
+
matrix_chain_answer(subproblem_count, Count) :- countall(subproblem(_I, _J, _Cost), Count).
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
% Missionaries-and-cannibals river crossing as a guarded state-space search.
|
|
2
|
+
materialize(missionaries_cannibals_answer, 2).
|
|
3
|
+
|
|
4
|
+
move(1, 0).
|
|
5
|
+
move(0, 1).
|
|
6
|
+
move(2, 0).
|
|
7
|
+
move(0, 2).
|
|
8
|
+
move(1, 1).
|
|
9
|
+
|
|
10
|
+
bank_safe(0, _C).
|
|
11
|
+
bank_safe(M, C) :- gt(M, 0), ge(M, C).
|
|
12
|
+
|
|
13
|
+
state_safe(state(MLeft, CLeft, _Boat)) :-
|
|
14
|
+
between(0, 3, MLeft),
|
|
15
|
+
between(0, 3, CLeft),
|
|
16
|
+
sub(3, MLeft, MRight),
|
|
17
|
+
sub(3, CLeft, CRight),
|
|
18
|
+
bank_safe(MLeft, CLeft),
|
|
19
|
+
bank_safe(MRight, CRight).
|
|
20
|
+
|
|
21
|
+
crossing(state(MLeft, CLeft, left), state(NextM, NextC, right), carry(MoveM, MoveC)) :-
|
|
22
|
+
move(MoveM, MoveC),
|
|
23
|
+
sub(MLeft, MoveM, NextM),
|
|
24
|
+
sub(CLeft, MoveC, NextC),
|
|
25
|
+
state_safe(state(NextM, NextC, right)).
|
|
26
|
+
crossing(state(MLeft, CLeft, right), state(NextM, NextC, left), carry(MoveM, MoveC)) :-
|
|
27
|
+
move(MoveM, MoveC),
|
|
28
|
+
add(MLeft, MoveM, NextM),
|
|
29
|
+
add(CLeft, MoveC, NextC),
|
|
30
|
+
state_safe(state(NextM, NextC, left)).
|
|
31
|
+
|
|
32
|
+
journey(Goal, Goal, Visited, Visited).
|
|
33
|
+
journey(State, Goal, Visited, Path) :-
|
|
34
|
+
crossing(State, Next, _Carry),
|
|
35
|
+
not_member(Next, Visited),
|
|
36
|
+
journey(Next, Goal, [Next|Visited], Path).
|
|
37
|
+
|
|
38
|
+
solution(Path) :-
|
|
39
|
+
journey(state(3, 3, left), state(0, 0, right), [state(3, 3, left)], ReversePath),
|
|
40
|
+
reverse(ReversePath, Path).
|
|
41
|
+
|
|
42
|
+
missionaries_cannibals_answer(first_solution, Path) :- once(solution(Path)).
|
|
43
|
+
missionaries_cannibals_answer(state_count, Count) :- countall(state_safe(state(_M, _C, _Boat)), Count).
|
|
44
|
+
missionaries_cannibals_answer(step_count, Steps) :-
|
|
45
|
+
once(solution(Path)),
|
|
46
|
+
length(Path, States),
|
|
47
|
+
sub(States, 1, Steps).
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
% Modular exponentiation by repeated squaring.
|
|
2
|
+
% pow_mod/4 is logarithmic in the exponent and memoized so repeated primality
|
|
3
|
+
% and congruence checks share subproblems.
|
|
4
|
+
materialize(modular_answer, 2).
|
|
5
|
+
|
|
6
|
+
memoize(pow_mod, 4).
|
|
7
|
+
|
|
8
|
+
pow_mod(_Base, 0, Mod, Result) :- mod(1, Mod, Result).
|
|
9
|
+
pow_mod(Base, Exp, Modulus, Result) :-
|
|
10
|
+
gt(Exp, 0),
|
|
11
|
+
mod(Exp, 2, 0),
|
|
12
|
+
div(Exp, 2, Half),
|
|
13
|
+
pow_mod(Base, Half, Modulus, HalfPower),
|
|
14
|
+
mul(HalfPower, HalfPower, Square),
|
|
15
|
+
mod(Square, Modulus, Result).
|
|
16
|
+
pow_mod(Base, Exp, Modulus, Result) :-
|
|
17
|
+
gt(Exp, 0),
|
|
18
|
+
mod(Exp, 2, 1),
|
|
19
|
+
sub(Exp, 1, EvenExp),
|
|
20
|
+
pow_mod(Base, EvenExp, Modulus, EvenPower),
|
|
21
|
+
mul(Base, EvenPower, Product),
|
|
22
|
+
mod(Product, Modulus, Result).
|
|
23
|
+
|
|
24
|
+
fermat_witness(Base, PrimeCandidate) :-
|
|
25
|
+
sub(PrimeCandidate, 1, Exponent),
|
|
26
|
+
pow_mod(Base, Exponent, PrimeCandidate, 1).
|
|
27
|
+
|
|
28
|
+
modular_answer(pow_7_560_mod_561, R) :- pow_mod(7, 560, 561, R).
|
|
29
|
+
modular_answer(pow_2_1000_mod_1009, R) :- pow_mod(2, 1000, 1009, R).
|
|
30
|
+
modular_answer(fermat_2_101, true) :- fermat_witness(2, 101).
|
|
31
|
+
modular_answer(fermat_3_101, true) :- fermat_witness(3, 101).
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
% N-queens search for the 8x8 board.
|
|
2
|
+
% This example enumerates all row permutations and filters diagonal attacks.
|
|
3
|
+
materialize(n_queens_answer, 2).
|
|
4
|
+
|
|
5
|
+
% Cache diagonal checks; the same row/distance/suffix states recur across
|
|
6
|
+
% many candidate permutations during the 8-queens search.
|
|
7
|
+
memoize(no_diagonal_attack, 3).
|
|
8
|
+
|
|
9
|
+
perm([], []).
|
|
10
|
+
perm(Items, [X|Rest]) :-
|
|
11
|
+
select(X, Items, Remaining),
|
|
12
|
+
perm(Remaining, Rest).
|
|
13
|
+
|
|
14
|
+
safe_rows([]).
|
|
15
|
+
safe_rows([Row|Rest]) :-
|
|
16
|
+
no_diagonal_attack(Row, 1, Rest),
|
|
17
|
+
safe_rows(Rest).
|
|
18
|
+
|
|
19
|
+
no_diagonal_attack(_Row, _Distance, []).
|
|
20
|
+
no_diagonal_attack(Row, Distance, [Other|Rest]) :-
|
|
21
|
+
sub(Row, Other, Delta),
|
|
22
|
+
abs(Delta, AbsDelta),
|
|
23
|
+
neq(AbsDelta, Distance),
|
|
24
|
+
add(Distance, 1, NextDistance),
|
|
25
|
+
no_diagonal_attack(Row, NextDistance, Rest).
|
|
26
|
+
|
|
27
|
+
queen_solution(Rows) :-
|
|
28
|
+
perm([1, 2, 3, 4, 5, 6, 7, 8], Rows),
|
|
29
|
+
safe_rows(Rows).
|
|
30
|
+
|
|
31
|
+
n_queens_answer(first_solution, Rows) :- once(queen_solution(Rows)).
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
chart_parser_answer(parsed, command).
|
|
2
|
+
chart_parser_answer(parsed, ambiguous_pp).
|
|
3
|
+
chart_parser_answer(parse_count, count(command, 1)).
|
|
4
|
+
chart_parser_answer(parse_count, count(ambiguous_pp, 1)).
|
|
5
|
+
chart_parser_answer(noun_phrase_count, count(command, 2)).
|
|
6
|
+
chart_parser_answer(noun_phrase_count, count(ambiguous_pp, 3)).
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
critical_path_answer(project_finish, 23).
|
|
2
|
+
critical_path_answer(critical_task, launch).
|
|
3
|
+
critical_path_answer(critical_task, security_review).
|
|
4
|
+
critical_path_answer(critical_task, integration).
|
|
5
|
+
critical_path_answer(critical_task, backend).
|
|
6
|
+
critical_path_answer(critical_task, database).
|
|
7
|
+
critical_path_answer(critical_task, architecture).
|
|
8
|
+
critical_path_answer(critical_task, requirements).
|
|
9
|
+
critical_path_answer(schedule, task(requirements, 0, 2)).
|
|
10
|
+
critical_path_answer(schedule, task(architecture, 2, 5)).
|
|
11
|
+
critical_path_answer(schedule, task(api_design, 2, 4)).
|
|
12
|
+
critical_path_answer(schedule, task(database, 5, 9)).
|
|
13
|
+
critical_path_answer(schedule, task(backend, 9, 15)).
|
|
14
|
+
critical_path_answer(schedule, task(frontend, 4, 9)).
|
|
15
|
+
critical_path_answer(schedule, task(auth, 5, 8)).
|
|
16
|
+
critical_path_answer(schedule, task(integration, 15, 19)).
|
|
17
|
+
critical_path_answer(schedule, task(security_review, 19, 22)).
|
|
18
|
+
critical_path_answer(schedule, task(load_test, 19, 21)).
|
|
19
|
+
critical_path_answer(schedule, task(launch, 22, 23)).
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
missionaries_cannibals_answer(first_solution, [state(3, 3, left), state(3, 1, right), state(3, 2, left), state(3, 0, right), state(3, 1, left), state(1, 1, right), state(2, 2, left), state(0, 2, right), state(0, 3, left), state(0, 1, right), state(1, 1, left), state(0, 0, right)]).
|
|
2
|
+
missionaries_cannibals_answer(state_count, 10).
|
|
3
|
+
missionaries_cannibals_answer(step_count, 11).
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
n_queens_answer(first_solution, [1, 5, 8, 6, 3, 7, 2, 4]).
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
weighted_interval_answer(best_value, 13).
|
|
2
|
+
weighted_interval_answer(chosen_interval, interval(1, 1, 4, 5)).
|
|
3
|
+
weighted_interval_answer(chosen_interval, interval(4, 4, 7, 4)).
|
|
4
|
+
weighted_interval_answer(chosen_interval, interval(8, 8, 11, 4)).
|
|
5
|
+
weighted_interval_answer(candidate_count, 8).
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
% Pell equation x^2 - 2 y^2 = 1 by memoized recurrence.
|
|
2
|
+
% The fundamental solution (3,2) generates all positive solutions.
|
|
3
|
+
materialize(pell_answer, 2).
|
|
4
|
+
|
|
5
|
+
memoize(pell, 3).
|
|
6
|
+
|
|
7
|
+
pell(0, 1, 0).
|
|
8
|
+
pell(N, X, Y) :-
|
|
9
|
+
gt(N, 0),
|
|
10
|
+
sub(N, 1, N1),
|
|
11
|
+
pell(N1, X0, Y0),
|
|
12
|
+
mul(3, X0, AX),
|
|
13
|
+
mul(4, Y0, BY),
|
|
14
|
+
add(AX, BY, X),
|
|
15
|
+
mul(2, X0, CX),
|
|
16
|
+
mul(3, Y0, DY),
|
|
17
|
+
add(CX, DY, Y).
|
|
18
|
+
|
|
19
|
+
pell_holds(N, true) :-
|
|
20
|
+
pell(N, X, Y),
|
|
21
|
+
mul(X, X, X2),
|
|
22
|
+
mul(Y, Y, Y2),
|
|
23
|
+
mul(2, Y2, TwiceY2),
|
|
24
|
+
sub(X2, TwiceY2, 1).
|
|
25
|
+
|
|
26
|
+
pell_answer(solution_5, solution(X, Y)) :- pell(5, X, Y).
|
|
27
|
+
pell_answer(solution_8, solution(X, Y)) :- pell(8, X, Y).
|
|
28
|
+
pell_answer(check_8, true) :- pell_holds(8, true).
|
|
29
|
+
pell_answer(y_sum_1_to_8, Sum) :- sumall(Y, (between(1, 8, N), pell(N, _X, Y)), Sum).
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
% Cryptarithm search for SEND + MORE = MONEY.
|
|
2
|
+
% Column constraints prune the digit assignment search.
|
|
3
|
+
materialize(cryptarithm_answer, 2).
|
|
4
|
+
|
|
5
|
+
all_digits([0, 1, 2, 3, 4, 5, 6, 7, 8, 9]).
|
|
6
|
+
|
|
7
|
+
send_more_money(solution(S, E, N, D, M, O, R, Y)) :-
|
|
8
|
+
all_digits(Digits),
|
|
9
|
+
eq(M, 1),
|
|
10
|
+
eq(O, 0),
|
|
11
|
+
select(M, Digits, D0),
|
|
12
|
+
select(O, D0, D1),
|
|
13
|
+
|
|
14
|
+
select(D, D1, D2),
|
|
15
|
+
select(E, D2, D3),
|
|
16
|
+
add(D, E, OnesSum),
|
|
17
|
+
mod(OnesSum, 10, Y),
|
|
18
|
+
div(OnesSum, 10, Carry1),
|
|
19
|
+
select(Y, D3, D4),
|
|
20
|
+
|
|
21
|
+
select(N, D4, D5),
|
|
22
|
+
select(R, D5, D6),
|
|
23
|
+
add(N, R, TensPartial),
|
|
24
|
+
add(TensPartial, Carry1, TensSum),
|
|
25
|
+
mod(TensSum, 10, E),
|
|
26
|
+
div(TensSum, 10, Carry2),
|
|
27
|
+
|
|
28
|
+
add(E, O, HundredsPartial),
|
|
29
|
+
add(HundredsPartial, Carry2, HundredsSum),
|
|
30
|
+
mod(HundredsSum, 10, N),
|
|
31
|
+
div(HundredsSum, 10, Carry3),
|
|
32
|
+
|
|
33
|
+
select(S, D6, _D7),
|
|
34
|
+
neq(S, 0),
|
|
35
|
+
add(S, M, ThousandsPartial),
|
|
36
|
+
add(ThousandsPartial, Carry3, ThousandsSum),
|
|
37
|
+
mod(ThousandsSum, 10, O),
|
|
38
|
+
div(ThousandsSum, 10, M).
|
|
39
|
+
|
|
40
|
+
number4(A, B, C, D, Value) :-
|
|
41
|
+
mul(A, 1000, APart),
|
|
42
|
+
mul(B, 100, BPart),
|
|
43
|
+
mul(C, 10, CPart),
|
|
44
|
+
add(APart, BPart, AB),
|
|
45
|
+
add(AB, CPart, ABC),
|
|
46
|
+
add(ABC, D, Value).
|
|
47
|
+
|
|
48
|
+
number5(A, B, C, D, E, Value) :-
|
|
49
|
+
mul(A, 10000, APart),
|
|
50
|
+
mul(B, 1000, BPart),
|
|
51
|
+
mul(C, 100, CPart),
|
|
52
|
+
mul(D, 10, DPart),
|
|
53
|
+
add(APart, BPart, AB),
|
|
54
|
+
add(AB, CPart, ABC),
|
|
55
|
+
add(ABC, DPart, ABCD),
|
|
56
|
+
add(ABCD, E, Value).
|
|
57
|
+
|
|
58
|
+
cryptarithm_answer(assignments, solution(S, E, N, D, M, O, R, Y)) :-
|
|
59
|
+
send_more_money(solution(S, E, N, D, M, O, R, Y)).
|
|
60
|
+
cryptarithm_answer(equation, equation(Send, More, Money)) :-
|
|
61
|
+
send_more_money(solution(S, E, N, D, M, O, R, Y)),
|
|
62
|
+
number4(S, E, N, D, Send),
|
|
63
|
+
number4(M, O, R, E, More),
|
|
64
|
+
number5(M, O, N, E, Y, Money).
|
|
65
|
+
cryptarithm_answer(solution_count, Count) :-
|
|
66
|
+
countall(send_more_money(_Solution), Count).
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
% Stable-marriage search with blocking-pair detection.
|
|
2
|
+
materialize(stable_marriage_answer, 2).
|
|
3
|
+
|
|
4
|
+
man(adam).
|
|
5
|
+
man(brian).
|
|
6
|
+
man(cole).
|
|
7
|
+
man(drew).
|
|
8
|
+
|
|
9
|
+
woman(amy).
|
|
10
|
+
woman(bea).
|
|
11
|
+
woman(cora).
|
|
12
|
+
woman(dana).
|
|
13
|
+
|
|
14
|
+
rank_man(adam, bea, 1).
|
|
15
|
+
rank_man(adam, amy, 2).
|
|
16
|
+
rank_man(adam, dana, 3).
|
|
17
|
+
rank_man(adam, cora, 4).
|
|
18
|
+
rank_man(brian, amy, 1).
|
|
19
|
+
rank_man(brian, cora, 2).
|
|
20
|
+
rank_man(brian, bea, 3).
|
|
21
|
+
rank_man(brian, dana, 4).
|
|
22
|
+
rank_man(cole, amy, 1).
|
|
23
|
+
rank_man(cole, bea, 2).
|
|
24
|
+
rank_man(cole, dana, 3).
|
|
25
|
+
rank_man(cole, cora, 4).
|
|
26
|
+
rank_man(drew, cora, 1).
|
|
27
|
+
rank_man(drew, dana, 2).
|
|
28
|
+
rank_man(drew, bea, 3).
|
|
29
|
+
rank_man(drew, amy, 4).
|
|
30
|
+
|
|
31
|
+
rank_woman(amy, cole, 1).
|
|
32
|
+
rank_woman(amy, adam, 2).
|
|
33
|
+
rank_woman(amy, brian, 3).
|
|
34
|
+
rank_woman(amy, drew, 4).
|
|
35
|
+
rank_woman(bea, adam, 1).
|
|
36
|
+
rank_woman(bea, cole, 2).
|
|
37
|
+
rank_woman(bea, drew, 3).
|
|
38
|
+
rank_woman(bea, brian, 4).
|
|
39
|
+
rank_woman(cora, drew, 1).
|
|
40
|
+
rank_woman(cora, brian, 2).
|
|
41
|
+
rank_woman(cora, adam, 3).
|
|
42
|
+
rank_woman(cora, cole, 4).
|
|
43
|
+
rank_woman(dana, brian, 1).
|
|
44
|
+
rank_woman(dana, drew, 2).
|
|
45
|
+
rank_woman(dana, cole, 3).
|
|
46
|
+
rank_woman(dana, adam, 4).
|
|
47
|
+
|
|
48
|
+
perm([], []).
|
|
49
|
+
perm(Items, [X|Rest]) :-
|
|
50
|
+
select(X, Items, Remaining),
|
|
51
|
+
perm(Remaining, Rest).
|
|
52
|
+
|
|
53
|
+
matching([
|
|
54
|
+
pair(adam, W1),
|
|
55
|
+
pair(brian, W2),
|
|
56
|
+
pair(cole, W3),
|
|
57
|
+
pair(drew, W4)
|
|
58
|
+
]) :-
|
|
59
|
+
perm([amy, bea, cora, dana], [W1, W2, W3, W4]).
|
|
60
|
+
|
|
61
|
+
assigned(Matching, Man, Woman) :- member(pair(Man, Woman), Matching).
|
|
62
|
+
|
|
63
|
+
prefers_man(Man, Candidate, Current) :-
|
|
64
|
+
rank_man(Man, Candidate, CandidateRank),
|
|
65
|
+
rank_man(Man, Current, CurrentRank),
|
|
66
|
+
lt(CandidateRank, CurrentRank).
|
|
67
|
+
|
|
68
|
+
prefers_woman(Woman, Candidate, Current) :-
|
|
69
|
+
rank_woman(Woman, Candidate, CandidateRank),
|
|
70
|
+
rank_woman(Woman, Current, CurrentRank),
|
|
71
|
+
lt(CandidateRank, CurrentRank).
|
|
72
|
+
|
|
73
|
+
blocking_pair(Matching, Man, Woman) :-
|
|
74
|
+
assigned(Matching, Man, CurrentWoman),
|
|
75
|
+
woman(Woman),
|
|
76
|
+
neq(Woman, CurrentWoman),
|
|
77
|
+
prefers_man(Man, Woman, CurrentWoman),
|
|
78
|
+
assigned(Matching, CurrentMan, Woman),
|
|
79
|
+
prefers_woman(Woman, Man, CurrentMan).
|
|
80
|
+
|
|
81
|
+
stable_matching(Matching) :-
|
|
82
|
+
matching(Matching),
|
|
83
|
+
not(blocking_pair(Matching, _Man, _Woman)).
|
|
84
|
+
|
|
85
|
+
stable_marriage_answer(first_stable_matching, Matching) :- once(stable_matching(Matching)).
|
|
86
|
+
stable_marriage_answer(stable_matching_count, Count) :- countall(stable_matching(_Matching), Count).
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
% Stirling numbers of the second kind and Bell numbers.
|
|
2
|
+
% stirling2(N, K, Count) partitions N labelled elements into K nonempty blocks.
|
|
3
|
+
materialize(stirling_bell_answer, 2).
|
|
4
|
+
|
|
5
|
+
memoize(stirling2, 3).
|
|
6
|
+
|
|
7
|
+
stirling2(0, 0, 1).
|
|
8
|
+
stirling2(N, 0, 0) :- gt(N, 0).
|
|
9
|
+
stirling2(0, K, 0) :- gt(K, 0).
|
|
10
|
+
stirling2(N, K, Count) :-
|
|
11
|
+
gt(N, 0),
|
|
12
|
+
gt(K, 0),
|
|
13
|
+
sub(N, 1, N1),
|
|
14
|
+
sub(K, 1, K1),
|
|
15
|
+
stirling2(N1, K1, NewBlock),
|
|
16
|
+
stirling2(N1, K, ExistingBlocks),
|
|
17
|
+
mul(K, ExistingBlocks, Extended),
|
|
18
|
+
add(NewBlock, Extended, Count).
|
|
19
|
+
|
|
20
|
+
bell(N, Count) :-
|
|
21
|
+
sumall(S, (between(0, N, K), stirling2(N, K, S)), Count).
|
|
22
|
+
|
|
23
|
+
stirling_bell_answer(stirling_10_4, Count) :- stirling2(10, 4, Count).
|
|
24
|
+
stirling_bell_answer(stirling_12_5, Count) :- stirling2(12, 5, Count).
|
|
25
|
+
stirling_bell_answer(bell_10, Count) :- bell(10, Count).
|
|
26
|
+
stirling_bell_answer(bell_12, Count) :- bell(12, Count).
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
% A compact 4x4 Sudoku search with row permutations and column/box constraints.
|
|
2
|
+
materialize(sudoku_answer, 2).
|
|
3
|
+
|
|
4
|
+
perm([], []).
|
|
5
|
+
perm(Items, [X|Rest]) :-
|
|
6
|
+
select(X, Items, Remaining),
|
|
7
|
+
perm(Remaining, Rest).
|
|
8
|
+
|
|
9
|
+
distinct([]).
|
|
10
|
+
distinct([X|Xs]) :-
|
|
11
|
+
not_member(X, Xs),
|
|
12
|
+
distinct(Xs).
|
|
13
|
+
|
|
14
|
+
row1([1, B, C, 4]) :- perm([1, 2, 3, 4], [1, B, C, 4]).
|
|
15
|
+
row2([A, 4, 1, D]) :- perm([1, 2, 3, 4], [A, 4, 1, D]).
|
|
16
|
+
row3([B, 1, 4, C]) :- perm([1, 2, 3, 4], [B, 1, 4, C]).
|
|
17
|
+
row4([4, C, B, 1]) :- perm([1, 2, 3, 4], [4, C, B, 1]).
|
|
18
|
+
|
|
19
|
+
column([R1, R2, R3, R4], Index, [A, B, C, D]) :-
|
|
20
|
+
nth0(Index, R1, A),
|
|
21
|
+
nth0(Index, R2, B),
|
|
22
|
+
nth0(Index, R3, C),
|
|
23
|
+
nth0(Index, R4, D).
|
|
24
|
+
|
|
25
|
+
boxes([R1, R2, R3, R4], [Box1, Box2, Box3, Box4]) :-
|
|
26
|
+
nth0(0, R1, A), nth0(1, R1, B), nth0(0, R2, C), nth0(1, R2, D),
|
|
27
|
+
eq(Box1, [A, B, C, D]),
|
|
28
|
+
nth0(2, R1, E), nth0(3, R1, F), nth0(2, R2, G), nth0(3, R2, H),
|
|
29
|
+
eq(Box2, [E, F, G, H]),
|
|
30
|
+
nth0(0, R3, I), nth0(1, R3, J), nth0(0, R4, K), nth0(1, R4, L),
|
|
31
|
+
eq(Box3, [I, J, K, L]),
|
|
32
|
+
nth0(2, R3, M), nth0(3, R3, N), nth0(2, R4, O), nth0(3, R4, P),
|
|
33
|
+
eq(Box4, [M, N, O, P]).
|
|
34
|
+
|
|
35
|
+
sudoku_solution([R1, R2, R3, R4]) :-
|
|
36
|
+
row1(R1),
|
|
37
|
+
row2(R2),
|
|
38
|
+
row3(R3),
|
|
39
|
+
row4(R4),
|
|
40
|
+
column([R1, R2, R3, R4], 0, C0), distinct(C0),
|
|
41
|
+
column([R1, R2, R3, R4], 1, C1), distinct(C1),
|
|
42
|
+
column([R1, R2, R3, R4], 2, C2), distinct(C2),
|
|
43
|
+
column([R1, R2, R3, R4], 3, C3), distinct(C3),
|
|
44
|
+
boxes([R1, R2, R3, R4], [B1, B2, B3, B4]),
|
|
45
|
+
distinct(B1), distinct(B2), distinct(B3), distinct(B4).
|
|
46
|
+
|
|
47
|
+
sudoku_answer(solution, Grid) :- once(sudoku_solution(Grid)).
|
|
48
|
+
sudoku_answer(solution_count, Count) :- countall(sudoku_solution(_Grid), Count).
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
% Euler totients and coprimality by memoized Euclidean gcd.
|
|
2
|
+
% This is still ordinary Horn-clause search: phi(N) is the count of K <= N
|
|
3
|
+
% with gcd(N, K) = 1.
|
|
4
|
+
materialize(totient_answer, 2).
|
|
5
|
+
|
|
6
|
+
memoize(gcd, 3).
|
|
7
|
+
memoize(totient, 2).
|
|
8
|
+
|
|
9
|
+
gcd(A, 0, A) :- ge(A, 0).
|
|
10
|
+
gcd(A, B, G) :-
|
|
11
|
+
gt(B, 0),
|
|
12
|
+
mod(A, B, R),
|
|
13
|
+
gcd(B, R, G).
|
|
14
|
+
|
|
15
|
+
coprime_upto(N, K) :-
|
|
16
|
+
between(1, N, K),
|
|
17
|
+
gcd(N, K, 1).
|
|
18
|
+
|
|
19
|
+
totient(N, Count) :-
|
|
20
|
+
gt(N, 0),
|
|
21
|
+
countall(coprime_upto(N, _K), Count).
|
|
22
|
+
|
|
23
|
+
summatory_totient(Limit, Sum) :-
|
|
24
|
+
sumall(Phi, (between(1, Limit, N), totient(N, Phi)), Sum).
|
|
25
|
+
|
|
26
|
+
totient_answer(phi_36, Phi) :- totient(36, Phi).
|
|
27
|
+
totient_answer(phi_97, Phi) :- totient(97, Phi).
|
|
28
|
+
totient_answer(coprime_count_84, Count) :- totient(84, Count).
|
|
29
|
+
totient_answer(summatory_phi_30, Sum) :- summatory_totient(30, Sum).
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
% Weighted interval scheduling via memoized dynamic programming.
|
|
2
|
+
% Intervals are already ordered by finish time; best_from/2 chooses take/skip.
|
|
3
|
+
materialize(weighted_interval_answer, 2).
|
|
4
|
+
|
|
5
|
+
memoize(best_from, 2).
|
|
6
|
+
|
|
7
|
+
last_interval(8).
|
|
8
|
+
sentinel(9).
|
|
9
|
+
|
|
10
|
+
interval(1, 1, 4, 5).
|
|
11
|
+
interval(2, 3, 5, 1).
|
|
12
|
+
interval(3, 0, 6, 8).
|
|
13
|
+
interval(4, 4, 7, 4).
|
|
14
|
+
interval(5, 3, 9, 6).
|
|
15
|
+
interval(6, 5, 9, 3).
|
|
16
|
+
interval(7, 6, 10, 2).
|
|
17
|
+
interval(8, 8, 11, 4).
|
|
18
|
+
|
|
19
|
+
next_compatible(I, J) :-
|
|
20
|
+
interval(I, _Start, Finish, _Value),
|
|
21
|
+
aggregate_min(K, K,
|
|
22
|
+
(interval(K, StartK, _FinishK, _ValueK), gt(K, I), ge(StartK, Finish)),
|
|
23
|
+
J, J).
|
|
24
|
+
next_compatible(I, 9) :-
|
|
25
|
+
interval(I, _Start, Finish, _Value),
|
|
26
|
+
not((interval(K, StartK, _FinishK, _ValueK), gt(K, I), ge(StartK, Finish))).
|
|
27
|
+
|
|
28
|
+
best_from(9, 0).
|
|
29
|
+
best_from(I, Best) :-
|
|
30
|
+
last_interval(Last),
|
|
31
|
+
le(I, Last),
|
|
32
|
+
add(I, 1, Next),
|
|
33
|
+
best_from(Next, Skip),
|
|
34
|
+
next_compatible(I, Compatible),
|
|
35
|
+
best_from(Compatible, Tail),
|
|
36
|
+
interval(I, _Start, _Finish, Value),
|
|
37
|
+
add(Value, Tail, Take),
|
|
38
|
+
max(Take, Skip, Best).
|
|
39
|
+
|
|
40
|
+
chosen_from(I, I) :-
|
|
41
|
+
best_from(I, Best),
|
|
42
|
+
add(I, 1, Next),
|
|
43
|
+
best_from(Next, Skip),
|
|
44
|
+
next_compatible(I, Compatible),
|
|
45
|
+
best_from(Compatible, Tail),
|
|
46
|
+
interval(I, _Start, _Finish, Value),
|
|
47
|
+
add(Value, Tail, Take),
|
|
48
|
+
eq(Best, Take),
|
|
49
|
+
ge(Take, Skip).
|
|
50
|
+
chosen_from(I, Chosen) :-
|
|
51
|
+
best_from(I, Best),
|
|
52
|
+
add(I, 1, Next),
|
|
53
|
+
best_from(Next, Skip),
|
|
54
|
+
next_compatible(I, Compatible),
|
|
55
|
+
best_from(Compatible, Tail),
|
|
56
|
+
interval(I, _Start, _Finish, Value),
|
|
57
|
+
add(Value, Tail, Take),
|
|
58
|
+
eq(Best, Take),
|
|
59
|
+
ge(Take, Skip),
|
|
60
|
+
chosen_from(Compatible, Chosen).
|
|
61
|
+
chosen_from(I, Chosen) :-
|
|
62
|
+
best_from(I, Best),
|
|
63
|
+
add(I, 1, Next),
|
|
64
|
+
best_from(Next, Skip),
|
|
65
|
+
next_compatible(I, Compatible),
|
|
66
|
+
best_from(Compatible, Tail),
|
|
67
|
+
interval(I, _Start, _Finish, Value),
|
|
68
|
+
add(Value, Tail, Take),
|
|
69
|
+
gt(Skip, Take),
|
|
70
|
+
chosen_from(Next, Chosen).
|
|
71
|
+
|
|
72
|
+
weighted_interval_answer(best_value, Best) :- best_from(1, Best).
|
|
73
|
+
weighted_interval_answer(chosen_interval, interval(I, Start, Finish, Value)) :-
|
|
74
|
+
chosen_from(1, I),
|
|
75
|
+
interval(I, Start, Finish, Value).
|
|
76
|
+
weighted_interval_answer(candidate_count, Count) :- countall(interval(_I, _Start, _Finish, _Value), Count).
|
package/package.json
CHANGED
package/playground.html
CHANGED
|
@@ -449,6 +449,7 @@
|
|
|
449
449
|
"bayes-diagnosis",
|
|
450
450
|
"bayes-therapy",
|
|
451
451
|
"beam-deflection",
|
|
452
|
+
"binomial-vandermonde",
|
|
452
453
|
"blocks-world-planning",
|
|
453
454
|
"bmi",
|
|
454
455
|
"braking-safety-worlds",
|
|
@@ -456,6 +457,8 @@
|
|
|
456
457
|
"cache-performance",
|
|
457
458
|
"canary-release",
|
|
458
459
|
"cat-koko",
|
|
460
|
+
"catalan-convolution",
|
|
461
|
+
"chart-parser",
|
|
459
462
|
"clinical-trial-screening",
|
|
460
463
|
"collatz-1000",
|
|
461
464
|
"combinatorics-findall-sort",
|
|
@@ -464,7 +467,9 @@
|
|
|
464
467
|
"composition-of-injective-functions-is-injective",
|
|
465
468
|
"context-association",
|
|
466
469
|
"context-schema-audit",
|
|
470
|
+
"continued-fraction-sqrt2",
|
|
467
471
|
"control-system",
|
|
472
|
+
"critical-path-schedule",
|
|
468
473
|
"cyclic-path",
|
|
469
474
|
"d3-group",
|
|
470
475
|
"dairy-energy-balance",
|
|
@@ -519,6 +524,7 @@
|
|
|
519
524
|
"heron-theorem",
|
|
520
525
|
"ideal-gas-law",
|
|
521
526
|
"illegitimate-reasoning",
|
|
527
|
+
"integer-partitions",
|
|
522
528
|
"job-shop-scheduling",
|
|
523
529
|
"knapsack-optimization",
|
|
524
530
|
"knowledge-engineering-alignment-flow",
|
|
@@ -527,7 +533,10 @@
|
|
|
527
533
|
"list-collection",
|
|
528
534
|
"lldm",
|
|
529
535
|
"manufacturing-quality-control",
|
|
536
|
+
"matrix-chain-order",
|
|
530
537
|
"microgrid-dispatch",
|
|
538
|
+
"missionaries-cannibals",
|
|
539
|
+
"modular-exponentiation",
|
|
531
540
|
"monkey-bananas",
|
|
532
541
|
"n-queens-8",
|
|
533
542
|
"network-sla",
|
|
@@ -541,6 +550,7 @@
|
|
|
541
550
|
"path-discovery",
|
|
542
551
|
"peano-arithmetic",
|
|
543
552
|
"peasant",
|
|
553
|
+
"pell-equation",
|
|
544
554
|
"pendulum-period",
|
|
545
555
|
"polynomial",
|
|
546
556
|
"proof-contrapositive",
|
|
@@ -558,12 +568,16 @@
|
|
|
558
568
|
"socrates",
|
|
559
569
|
"stable-marriage",
|
|
560
570
|
"statistics-summary",
|
|
571
|
+
"stirling-bell-numbers",
|
|
572
|
+
"sudoku-4x4",
|
|
561
573
|
"superdense-coding",
|
|
562
574
|
"term-tools",
|
|
575
|
+
"totient-summatory",
|
|
563
576
|
"trust-flow-provenance-threshold",
|
|
564
577
|
"turing",
|
|
565
578
|
"vector-similarity",
|
|
566
579
|
"vulnerability-impact",
|
|
580
|
+
"weighted-interval-scheduling",
|
|
567
581
|
"witch",
|
|
568
582
|
"wolf-goat-cabbage",
|
|
569
583
|
"zebra"
|
package/test/run-regression.mjs
CHANGED
|
@@ -524,6 +524,35 @@ function whiteBoxCases() {
|
|
|
524
524
|
assertEqual(termToString(candidates.primary[0].head, new Env(), true), 'edge(a, b)', 'primary head');
|
|
525
525
|
},
|
|
526
526
|
},
|
|
527
|
+
{
|
|
528
|
+
name: 'challenging examples keep dynamic-programming predicates memoized',
|
|
529
|
+
run: () => {
|
|
530
|
+
const checks = [
|
|
531
|
+
['binomial-vandermonde.pl', 'choose_step', 5, true],
|
|
532
|
+
['catalan-convolution.pl', 'catalan', 2, false],
|
|
533
|
+
['chart-parser.pl', 'span', 4, true],
|
|
534
|
+
['continued-fraction-sqrt2.pl', 'conv', 3, true],
|
|
535
|
+
['critical-path-schedule.pl', 'earliest_start', 2, false],
|
|
536
|
+
['critical-path-schedule.pl', 'finish_time', 2, false],
|
|
537
|
+
['integer-partitions.pl', 'partitions', 3, true],
|
|
538
|
+
['matrix-chain-order.pl', 'cost', 3, false],
|
|
539
|
+
['modular-exponentiation.pl', 'pow_mod', 4, true],
|
|
540
|
+
['pell-equation.pl', 'pell', 3, true],
|
|
541
|
+
['stirling-bell-numbers.pl', 'stirling2', 3, true],
|
|
542
|
+
['totient-summatory.pl', 'gcd', 3, true],
|
|
543
|
+
['totient-summatory.pl', 'totient', 2, false],
|
|
544
|
+
['weighted-interval-scheduling.pl', 'best_from', 2, true],
|
|
545
|
+
];
|
|
546
|
+
for (const [filename, name, arity, recursive] of checks) {
|
|
547
|
+
const text = fs.readFileSync(path.join(packageRoot, 'examples', filename), 'utf8');
|
|
548
|
+
const program = Program.parseSources([{ text, filename }]);
|
|
549
|
+
const group = program.findGroup(name, arity);
|
|
550
|
+
assertEqual(Boolean(group), true, `${filename} ${name}/${arity} group exists`);
|
|
551
|
+
assertEqual(group.memoized, true, `${filename} ${name}/${arity} memoized`);
|
|
552
|
+
assertEqual(group.recursive, recursive, `${filename} ${name}/${arity} recursive`);
|
|
553
|
+
}
|
|
554
|
+
},
|
|
555
|
+
},
|
|
527
556
|
{
|
|
528
557
|
name: 'n-queens example keeps diagonal checks memoized',
|
|
529
558
|
run: () => {
|