eyelang 1.1.14 → 1.1.16
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 +14 -3
- package/examples/chart-parser.pl +59 -0
- package/examples/critical-path-schedule.pl +77 -0
- package/examples/job-shop-scheduling.pl +44 -0
- package/examples/knapsack-optimization.pl +40 -0
- package/examples/missionaries-cannibals.pl +47 -0
- package/examples/n-queens-8.pl +31 -0
- package/examples/output/chart-parser.pl +6 -0
- package/examples/output/critical-path-schedule.pl +19 -0
- package/examples/output/job-shop-scheduling.pl +3 -0
- package/examples/output/knapsack-optimization.pl +4 -0
- package/examples/output/missionaries-cannibals.pl +3 -0
- package/examples/output/n-queens-8.pl +1 -0
- package/examples/output/send-more-money.pl +3 -0
- package/examples/output/stable-marriage.pl +2 -0
- package/examples/output/sudoku-4x4.pl +2 -0
- package/examples/output/weighted-interval-scheduling.pl +5 -0
- package/examples/send-more-money.pl +66 -0
- package/examples/stable-marriage.pl +86 -0
- package/examples/sudoku-4x4.pl +48 -0
- package/examples/weighted-interval-scheduling.pl +76 -0
- package/package.json +1 -1
- package/playground.html +152 -136
- package/test/run-regression.mjs +33 -0
package/docs/guide.md
CHANGED
|
@@ -302,10 +302,10 @@ Use `holds/2` when you want to match the member term directly, for example `name
|
|
|
302
302
|
|
|
303
303
|
## Example catalog
|
|
304
304
|
|
|
305
|
-
|
|
305
|
+
Each example has a checked golden output in `examples/output`.
|
|
306
306
|
|
|
307
|
-
|
|
|
308
|
-
|
|
307
|
+
| Example | What it demonstrates | Golden output |
|
|
308
|
+
|---|---|---|
|
|
309
309
|
| [`access-control-policy.pl`](../examples/access-control-policy.pl) | Evaluates role and condition based access decisions. | [`output/access-control-policy.pl`](../examples/output/access-control-policy.pl) |
|
|
310
310
|
| [`ackermann.pl`](../examples/ackermann.pl) | Computes Ackermann-style hyperoperation values. | [`output/ackermann.pl`](../examples/output/ackermann.pl) |
|
|
311
311
|
| [`age.pl`](../examples/age.pl) | Checks whether people meet age thresholds. | [`output/age.pl`](../examples/output/age.pl) |
|
|
@@ -328,6 +328,7 @@ The repository includes examples for recursion, graph reachability, finite searc
|
|
|
328
328
|
| [`cache-performance.pl`](../examples/cache-performance.pl) | Summarizes cache latency performance. | [`output/cache-performance.pl`](../examples/output/cache-performance.pl) |
|
|
329
329
|
| [`canary-release.pl`](../examples/canary-release.pl) | Decides canary rollout or rollback. | [`output/canary-release.pl`](../examples/output/canary-release.pl) |
|
|
330
330
|
| [`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) |
|
|
331
|
+
| [`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
332
|
| [`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
333
|
| [`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
334
|
| [`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) |
|
|
@@ -337,6 +338,7 @@ The repository includes examples for recursion, graph reachability, finite searc
|
|
|
337
338
|
| [`context-association.pl`](../examples/context-association.pl) | Associates named contexts with their contents. | [`output/context-association.pl`](../examples/output/context-association.pl) |
|
|
338
339
|
| [`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) |
|
|
339
340
|
| [`control-system.pl`](../examples/control-system.pl) | Evaluates control-system measurements and targets. | [`output/control-system.pl`](../examples/output/control-system.pl) |
|
|
341
|
+
| [`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
342
|
| [`cyclic-path.pl`](../examples/cyclic-path.pl) | Computes paths in a cyclic graph. | [`output/cyclic-path.pl`](../examples/output/cyclic-path.pl) |
|
|
341
343
|
| [`d3-group.pl`](../examples/d3-group.pl) | Enumerates subgroups of the D3 group. | [`output/d3-group.pl`](../examples/output/d3-group.pl) |
|
|
342
344
|
| [`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 +393,8 @@ The repository includes examples for recursion, graph reachability, finite searc
|
|
|
391
393
|
| [`heron-theorem.pl`](../examples/heron-theorem.pl) | Computes triangle area by Heron's theorem. | [`output/heron-theorem.pl`](../examples/output/heron-theorem.pl) |
|
|
392
394
|
| [`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
395
|
| [`illegitimate-reasoning.pl`](../examples/illegitimate-reasoning.pl) | Detects suspect reasoning patterns. | [`output/illegitimate-reasoning.pl`](../examples/output/illegitimate-reasoning.pl) |
|
|
396
|
+
| [`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) |
|
|
397
|
+
| [`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) |
|
|
394
398
|
| [`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) |
|
|
395
399
|
| [`law-of-cosines.pl`](../examples/law-of-cosines.pl) | Computes a triangle side by cosine law. | [`output/law-of-cosines.pl`](../examples/output/law-of-cosines.pl) |
|
|
396
400
|
| [`least-squares-regression.pl`](../examples/least-squares-regression.pl) | Fits a least-squares regression line. | [`output/least-squares-regression.pl`](../examples/output/least-squares-regression.pl) |
|
|
@@ -398,7 +402,9 @@ The repository includes examples for recursion, graph reachability, finite searc
|
|
|
398
402
|
| [`lldm.pl`](../examples/lldm.pl) | Calculates leg-length discrepancy measurements. | [`output/lldm.pl`](../examples/output/lldm.pl) |
|
|
399
403
|
| [`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) |
|
|
400
404
|
| [`microgrid-dispatch.pl`](../examples/microgrid-dispatch.pl) | Plans microgrid dispatch and reserve. | [`output/microgrid-dispatch.pl`](../examples/output/microgrid-dispatch.pl) |
|
|
405
|
+
| [`missionaries-cannibals.pl`](../examples/missionaries-cannibals.pl) | Solves the missionaries-and-cannibals river crossing puzzle. | [`output/missionaries-cannibals.pl`](../examples/output/missionaries-cannibals.pl) |
|
|
401
406
|
| [`monkey-bananas.pl`](../examples/monkey-bananas.pl) | Solves the monkey-and-bananas puzzle. | [`output/monkey-bananas.pl`](../examples/output/monkey-bananas.pl) |
|
|
407
|
+
| [`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) |
|
|
402
408
|
| [`network-sla.pl`](../examples/network-sla.pl) | Checks network path SLA compliance. | [`output/network-sla.pl`](../examples/output/network-sla.pl) |
|
|
403
409
|
| [`newton-raphson.pl`](../examples/newton-raphson.pl) | Finds roots by Newton-Raphson iteration. | [`output/newton-raphson.pl`](../examples/output/newton-raphson.pl) |
|
|
404
410
|
| [`nixon-diamond.pl`](../examples/nixon-diamond.pl) | Reports the classic Nixon-diamond conflict. | [`output/nixon-diamond.pl`](../examples/output/nixon-diamond.pl) |
|
|
@@ -418,24 +424,29 @@ The repository includes examples for recursion, graph reachability, finite searc
|
|
|
418
424
|
| [`reusable-builtins.pl`](../examples/reusable-builtins.pl) | Tours reusable numeric, list, and string builtins. | [`output/reusable-builtins.pl`](../examples/output/reusable-builtins.pl) |
|
|
419
425
|
| [`riemann-hypothesis.pl`](../examples/riemann-hypothesis.pl) | Checks a finite catalogue of non-trivial zeta zeros against the Riemann-hypothesis condition. | [`output/riemann-hypothesis.pl`](../examples/output/riemann-hypothesis.pl) |
|
|
420
426
|
| [`security-incident-correlation.pl`](../examples/security-incident-correlation.pl) | Correlates security incidents across signals. | [`output/security-incident-correlation.pl`](../examples/output/security-incident-correlation.pl) |
|
|
427
|
+
| [`send-more-money.pl`](../examples/send-more-money.pl) | Solves the SEND + MORE = MONEY cryptarithm. | [`output/send-more-money.pl`](../examples/output/send-more-money.pl) |
|
|
421
428
|
| [`service-impact.pl`](../examples/service-impact.pl) | Analyzes service impact over cyclic dependencies. | [`output/service-impact.pl`](../examples/output/service-impact.pl) |
|
|
422
429
|
| [`sieve.pl`](../examples/sieve.pl) | Enumerates primes with a sieve-style program. | [`output/sieve.pl`](../examples/output/sieve.pl) |
|
|
423
430
|
| [`skolem-functions.pl`](../examples/skolem-functions.pl) | Generates deterministic functional terms. | [`output/skolem-functions.pl`](../examples/output/skolem-functions.pl) |
|
|
424
431
|
| [`socket-age.pl`](../examples/socket-age.pl) | Shows socket-declared age reasoning inputs and plugs. | [`output/socket-age.pl`](../examples/output/socket-age.pl) |
|
|
425
432
|
| [`socket-family.pl`](../examples/socket-family.pl) | Shows socket-declared family-source inputs and ancestry rules. | [`output/socket-family.pl`](../examples/output/socket-family.pl) |
|
|
426
433
|
| [`socrates.pl`](../examples/socrates.pl) | Derives that Socrates is mortal. | [`output/socrates.pl`](../examples/output/socrates.pl) |
|
|
434
|
+
| [`stable-marriage.pl`](../examples/stable-marriage.pl) | Finds stable matchings by excluding blocking pairs. | [`output/stable-marriage.pl`](../examples/output/stable-marriage.pl) |
|
|
427
435
|
| [`statistics-summary.pl`](../examples/statistics-summary.pl) | Computes population statistics for a sample. | [`output/statistics-summary.pl`](../examples/output/statistics-summary.pl) |
|
|
436
|
+
| [`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) |
|
|
428
437
|
| [`superdense-coding.pl`](../examples/superdense-coding.pl) | Models superdense-coding bit transmission. | [`output/superdense-coding.pl`](../examples/output/superdense-coding.pl) |
|
|
429
438
|
| [`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) |
|
|
430
439
|
| [`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) |
|
|
431
440
|
| [`turing.pl`](../examples/turing.pl) | Simulates a binary-increment Turing machine. | [`output/turing.pl`](../examples/output/turing.pl) |
|
|
432
441
|
| [`vector-similarity.pl`](../examples/vector-similarity.pl) | Computes dot product, norm, and cosine similarity. | [`output/vector-similarity.pl`](../examples/output/vector-similarity.pl) |
|
|
433
442
|
| [`vulnerability-impact.pl`](../examples/vulnerability-impact.pl) | Analyzes vulnerable transitive dependencies and urgent patch impact. | [`output/vulnerability-impact.pl`](../examples/output/vulnerability-impact.pl) |
|
|
443
|
+
| [`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) |
|
|
434
444
|
| [`witch.pl`](../examples/witch.pl) | Derives the classic “burn the witch” rule chain. | [`output/witch.pl`](../examples/output/witch.pl) |
|
|
435
445
|
| [`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) |
|
|
436
446
|
| [`zebra.pl`](../examples/zebra.pl) | Solves the zebra logic puzzle. | [`output/zebra.pl`](../examples/output/zebra.pl) |
|
|
437
447
|
|
|
438
448
|
|
|
449
|
+
|
|
439
450
|
## Golden outputs, tests, and conformance
|
|
440
451
|
|
|
441
452
|
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:
|
|
@@ -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,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,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,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
|
+
% 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,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,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,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
|
@@ -434,135 +434,145 @@
|
|
|
434
434
|
|
|
435
435
|
<script type="module">
|
|
436
436
|
const EXAMPLES = [
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
437
|
+
"access-control-policy",
|
|
438
|
+
"ackermann",
|
|
439
|
+
"age",
|
|
440
|
+
"aliases-and-namespaces",
|
|
441
|
+
"alignment-demo",
|
|
442
|
+
"allen-interval-calculus",
|
|
443
|
+
"ancestor",
|
|
444
|
+
"animal",
|
|
445
|
+
"annotation",
|
|
446
|
+
"auroracare",
|
|
447
|
+
"backward",
|
|
448
|
+
"basic-monadic",
|
|
449
|
+
"bayes-diagnosis",
|
|
450
|
+
"bayes-therapy",
|
|
451
|
+
"beam-deflection",
|
|
452
|
+
"blocks-world-planning",
|
|
453
|
+
"bmi",
|
|
454
|
+
"braking-safety-worlds",
|
|
455
|
+
"buck-converter-design",
|
|
456
|
+
"cache-performance",
|
|
457
|
+
"canary-release",
|
|
458
|
+
"cat-koko",
|
|
459
|
+
"chart-parser",
|
|
460
|
+
"clinical-trial-screening",
|
|
461
|
+
"collatz-1000",
|
|
462
|
+
"combinatorics-findall-sort",
|
|
463
|
+
"competitive-enzyme-kinetics",
|
|
464
|
+
"complex",
|
|
465
|
+
"composition-of-injective-functions-is-injective",
|
|
466
|
+
"context-association",
|
|
467
|
+
"context-schema-audit",
|
|
468
|
+
"control-system",
|
|
469
|
+
"critical-path-schedule",
|
|
470
|
+
"cyclic-path",
|
|
471
|
+
"d3-group",
|
|
472
|
+
"dairy-energy-balance",
|
|
473
|
+
"data-negotiation",
|
|
474
|
+
"deep-taxonomy-10",
|
|
475
|
+
"deep-taxonomy-100",
|
|
476
|
+
"deep-taxonomy-1000",
|
|
477
|
+
"deep-taxonomy-10000",
|
|
478
|
+
"deep-taxonomy-100000",
|
|
479
|
+
"delfour",
|
|
480
|
+
"deontic-logic",
|
|
481
|
+
"derived-backward-rule",
|
|
482
|
+
"derived-rule",
|
|
483
|
+
"diamond-property",
|
|
484
|
+
"dijkstra",
|
|
485
|
+
"dijkstra-findall-sort",
|
|
486
|
+
"dijkstra-risk-path",
|
|
487
|
+
"dining-philosophers",
|
|
488
|
+
"dog",
|
|
489
|
+
"dpv-odrl-purpose-mapping",
|
|
490
|
+
"drone-corridor-planner",
|
|
491
|
+
"easter-computus",
|
|
492
|
+
"electrical-rc-filter",
|
|
493
|
+
"epidemic-policy",
|
|
494
|
+
"equivalence-classes-overlap-implies-same-class",
|
|
495
|
+
"eulerian-path",
|
|
496
|
+
"ev-range-worlds",
|
|
497
|
+
"existential-rule",
|
|
498
|
+
"exoplanet-validation-worlds",
|
|
499
|
+
"expression-eval",
|
|
500
|
+
"family-cousins",
|
|
501
|
+
"fastpow",
|
|
502
|
+
"fft8-numeric",
|
|
503
|
+
"fibonacci",
|
|
504
|
+
"field-nitrogen-balance",
|
|
505
|
+
"flandor",
|
|
506
|
+
"floating-point",
|
|
507
|
+
"four-color-map",
|
|
508
|
+
"fundamental-theorem-arithmetic",
|
|
509
|
+
"gd-step-certified",
|
|
510
|
+
"gdpr-compliance",
|
|
511
|
+
"good-cobbler",
|
|
512
|
+
"gps",
|
|
513
|
+
"graph-reachability",
|
|
514
|
+
"gray-code-counter",
|
|
515
|
+
"greatest-lower-bound-uniqueness",
|
|
516
|
+
"group-inverse-uniqueness",
|
|
517
|
+
"hamiltonian-path",
|
|
518
|
+
"hamming-code",
|
|
519
|
+
"hanoi",
|
|
520
|
+
"heat-loss",
|
|
521
|
+
"heron-theorem",
|
|
522
|
+
"ideal-gas-law",
|
|
523
|
+
"illegitimate-reasoning",
|
|
524
|
+
"job-shop-scheduling",
|
|
525
|
+
"knapsack-optimization",
|
|
526
|
+
"knowledge-engineering-alignment-flow",
|
|
527
|
+
"law-of-cosines",
|
|
528
|
+
"least-squares-regression",
|
|
529
|
+
"list-collection",
|
|
530
|
+
"lldm",
|
|
531
|
+
"manufacturing-quality-control",
|
|
532
|
+
"microgrid-dispatch",
|
|
533
|
+
"missionaries-cannibals",
|
|
534
|
+
"monkey-bananas",
|
|
535
|
+
"n-queens-8",
|
|
536
|
+
"network-sla",
|
|
537
|
+
"newton-raphson",
|
|
538
|
+
"nixon-diamond",
|
|
539
|
+
"observability-log-correlation",
|
|
540
|
+
"odrl-dpv-fpv-trust-flow",
|
|
541
|
+
"odrl-dpv-healthcare-risk-ranked",
|
|
542
|
+
"odrl-dpv-risk-ranked",
|
|
543
|
+
"orbital-transfer-design",
|
|
544
|
+
"path-discovery",
|
|
545
|
+
"peano-arithmetic",
|
|
546
|
+
"peasant",
|
|
547
|
+
"pendulum-period",
|
|
548
|
+
"polynomial",
|
|
549
|
+
"proof-contrapositive",
|
|
550
|
+
"quadratic-formula",
|
|
551
|
+
"radioactive-decay",
|
|
552
|
+
"reusable-builtins",
|
|
553
|
+
"riemann-hypothesis",
|
|
554
|
+
"security-incident-correlation",
|
|
555
|
+
"send-more-money",
|
|
556
|
+
"service-impact",
|
|
557
|
+
"sieve",
|
|
558
|
+
"skolem-functions",
|
|
559
|
+
"socket-age",
|
|
560
|
+
"socket-family",
|
|
561
|
+
"socrates",
|
|
562
|
+
"stable-marriage",
|
|
563
|
+
"statistics-summary",
|
|
564
|
+
"sudoku-4x4",
|
|
565
|
+
"superdense-coding",
|
|
566
|
+
"term-tools",
|
|
567
|
+
"trust-flow-provenance-threshold",
|
|
568
|
+
"turing",
|
|
569
|
+
"vector-similarity",
|
|
570
|
+
"vulnerability-impact",
|
|
571
|
+
"weighted-interval-scheduling",
|
|
572
|
+
"witch",
|
|
573
|
+
"wolf-goat-cabbage",
|
|
574
|
+
"zebra"
|
|
575
|
+
];
|
|
566
576
|
const FALLBACK_SOURCE = `materialize(answer, 1).
|
|
567
577
|
answer(ok) :- eq(ok, ok).
|
|
568
578
|
`;
|
|
@@ -1015,11 +1025,13 @@ answer(ok) :- eq(ok, ok).
|
|
|
1015
1025
|
|
|
1016
1026
|
async function copyShareLink() {
|
|
1017
1027
|
const link = buildShareLink();
|
|
1018
|
-
if (link
|
|
1019
|
-
|
|
1028
|
+
if (link != null) {
|
|
1029
|
+
await copyText(link, 'Share link copied.');
|
|
1020
1030
|
return;
|
|
1021
1031
|
}
|
|
1022
|
-
await
|
|
1032
|
+
await createGistShare({
|
|
1033
|
+
reason: 'This program is too large for an inline URL, so Copy share link will create a Gist share instead.',
|
|
1034
|
+
});
|
|
1023
1035
|
}
|
|
1024
1036
|
|
|
1025
1037
|
function buildShareLink() {
|
|
@@ -1043,12 +1055,16 @@ answer(ok) :- eq(ok, ok).
|
|
|
1043
1055
|
return `${basePlaygroundUrl()}#${params.toString()}`;
|
|
1044
1056
|
}
|
|
1045
1057
|
|
|
1046
|
-
async function createGistShare() {
|
|
1058
|
+
async function createGistShare(options = {}) {
|
|
1047
1059
|
const stateText = JSON.stringify(currentShareState(), null, 2);
|
|
1048
|
-
|
|
1049
|
-
|
|
1060
|
+
if (options.reason) setStatus(options.reason);
|
|
1061
|
+
const token = prompt(`${options.reason ? `${options.reason}\n\n` : ''}Optional GitHub token with gist scope. It is only sent to api.github.com and is not stored. Leave blank to copy Gist-ready state and open gist.github.com.`);
|
|
1062
|
+
if (token === null) {
|
|
1063
|
+
setStatus('Gist share cancelled.');
|
|
1064
|
+
return;
|
|
1065
|
+
}
|
|
1050
1066
|
if (!token.trim()) {
|
|
1051
|
-
await copyText(stateText, `Gist-ready state copied. Create a Gist file named ${GIST_STATE_FILENAME}, paste it, then
|
|
1067
|
+
await copyText(stateText, `Gist-ready state copied. Create a Gist file named ${GIST_STATE_FILENAME}, paste it, then copy its raw URL into a playground #state-url link.`);
|
|
1052
1068
|
window.open('https://gist.github.com/', '_blank', 'noopener');
|
|
1053
1069
|
return;
|
|
1054
1070
|
}
|
package/test/run-regression.mjs
CHANGED
|
@@ -524,6 +524,36 @@ 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
|
+
['chart-parser.pl', 'span', 4, true],
|
|
532
|
+
['critical-path-schedule.pl', 'earliest_start', 2, false],
|
|
533
|
+
['critical-path-schedule.pl', 'finish_time', 2, false],
|
|
534
|
+
['weighted-interval-scheduling.pl', 'best_from', 2, true],
|
|
535
|
+
];
|
|
536
|
+
for (const [filename, name, arity, recursive] of checks) {
|
|
537
|
+
const text = fs.readFileSync(path.join(packageRoot, 'examples', filename), 'utf8');
|
|
538
|
+
const program = Program.parseSources([{ text, filename }]);
|
|
539
|
+
const group = program.findGroup(name, arity);
|
|
540
|
+
assertEqual(Boolean(group), true, `${filename} ${name}/${arity} group exists`);
|
|
541
|
+
assertEqual(group.memoized, true, `${filename} ${name}/${arity} memoized`);
|
|
542
|
+
assertEqual(group.recursive, recursive, `${filename} ${name}/${arity} recursive`);
|
|
543
|
+
}
|
|
544
|
+
},
|
|
545
|
+
},
|
|
546
|
+
{
|
|
547
|
+
name: 'n-queens example keeps diagonal checks memoized',
|
|
548
|
+
run: () => {
|
|
549
|
+
const text = fs.readFileSync(path.join(packageRoot, 'examples', 'n-queens-8.pl'), 'utf8');
|
|
550
|
+
const program = Program.parseSources([{ text, filename: 'n-queens-8.pl' }]);
|
|
551
|
+
const group = program.findGroup('no_diagonal_attack', 3);
|
|
552
|
+
assertEqual(Boolean(group), true, 'no_diagonal_attack/3 group exists');
|
|
553
|
+
assertEqual(group.memoized, true, 'no_diagonal_attack/3 memoized');
|
|
554
|
+
assertEqual(group.recursive, true, 'no_diagonal_attack/3 recursive');
|
|
555
|
+
},
|
|
556
|
+
},
|
|
527
557
|
{
|
|
528
558
|
name: 'collatz example keeps recursive trajectory predicate memoized',
|
|
529
559
|
run: () => {
|
|
@@ -684,6 +714,9 @@ function playgroundStaticIssues() {
|
|
|
684
714
|
if (!html.includes('id="create-gist"') || !html.includes('createGistShare') || !html.includes('GIST_STATE_FILENAME') || !html.includes("fetch('https://api.github.com/gists'")) {
|
|
685
715
|
issues.push('playground must support Gist-backed sharing for large programs');
|
|
686
716
|
}
|
|
717
|
+
if (!html.includes('await createGistShare({') || html.includes('Use “Create Gist share” instead')) {
|
|
718
|
+
issues.push('playground Copy share link must automatically fall back to Gist sharing for large programs');
|
|
719
|
+
}
|
|
687
720
|
if (!html.includes("params.has('state-url')") || !html.includes('#state-url=')) {
|
|
688
721
|
issues.push('playground must restore state from raw Gist state URLs');
|
|
689
722
|
}
|