eyeprolog 1.6.19 → 1.6.21

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.
Files changed (99) hide show
  1. package/examples/check/access-control-policy.pl +2 -1
  2. package/examples/check/attributed-variables.pl +3 -1
  3. package/examples/check/binomial-vandermonde.pl +2 -1
  4. package/examples/check/blocks-world-planning.pl +13 -2
  5. package/examples/check/catalan-convolution.pl +2 -1
  6. package/examples/check/cdcl-sat-solver.pl +2 -1
  7. package/examples/check/chart-parser.pl +4 -1
  8. package/examples/check/clinical-trial-screening.pl +3 -1
  9. package/examples/check/clpb-boolean-circuit.pl +5 -1
  10. package/examples/check/clpb-cardinality.pl +3 -1
  11. package/examples/check/clpb-feature-model.pl +5 -1
  12. package/examples/check/clpz-resource-allocation.pl +1 -1
  13. package/examples/check/combinatorics-findall-sort.pl +1 -1
  14. package/examples/check/context-schema-audit.pl +2 -1
  15. package/examples/check/continued-fraction-sqrt2.pl +1 -1
  16. package/examples/check/critical-path-schedule.pl +12 -2
  17. package/examples/check/d3-group.pl +1 -1
  18. package/examples/check/data-negotiation.pl +1 -1
  19. package/examples/check/dcg-command-parser.pl +4 -2
  20. package/examples/check/dcg-expression-language.pl +6 -2
  21. package/examples/check/deep-taxonomy-1000.pl +6 -1
  22. package/examples/check/deep-taxonomy-10000.pl +6 -1
  23. package/examples/check/deep-taxonomy-100000.pl +6 -1
  24. package/examples/check/defeasible-reasoning.pl +5 -1
  25. package/examples/check/delfour.pl +2 -1
  26. package/examples/check/dijkstra-findall-sort.pl +11 -1
  27. package/examples/check/dijkstra.pl +17 -1
  28. package/examples/check/dog.pl +1 -1
  29. package/examples/check/donald-gerald-robert.pl +1 -1
  30. package/examples/check/enigma1225.pl +1 -1
  31. package/examples/check/equality-saturation.pl +2 -1
  32. package/examples/check/eulerian-path.pl +3 -1
  33. package/examples/check/evidence-demand-authority.pl +14 -0
  34. package/examples/check/explainable-ev-depot-configuration.pl +1 -1
  35. package/examples/check/flandor.pl +2 -1
  36. package/examples/check/four-color-map.pl +2 -1
  37. package/examples/check/gdpr-compliance.pl +4 -1
  38. package/examples/check/graph-reachability.pl +7 -1
  39. package/examples/check/hamiltonian-path.pl +408 -1
  40. package/examples/check/integer-partitions.pl +1 -1
  41. package/examples/check/intuitionistic-logic-kripke.pl +4 -1
  42. package/examples/check/iso-control-and-errors.pl +3 -1
  43. package/examples/check/iso-dynamic-database.pl +4 -4
  44. package/examples/check/iso-extension-pipeline-audit.pl +5 -2
  45. package/examples/check/iso-extensions.pl +5 -3
  46. package/examples/check/iso-grouped-solutions.pl +5 -3
  47. package/examples/check/iso-operators.pl +1 -1
  48. package/examples/check/iso-term-io.pl +13 -1
  49. package/examples/check/job-shop-scheduling.pl +2 -1
  50. package/examples/check/json.pl +2 -1
  51. package/examples/check/knapsack-optimization.pl +2 -1
  52. package/examples/check/knights-tour-warnsdorff.pl +24 -1
  53. package/examples/check/knuth-bendix-completion.pl +5 -2
  54. package/examples/check/lee.pl +15 -1
  55. package/examples/check/linear-logic-resources.pl +1 -1
  56. package/examples/check/map-four-color-search.pl +27 -1
  57. package/examples/check/markov-logic-network.pl +10 -2
  58. package/examples/check/matrix-chain-order.pl +7 -1
  59. package/examples/check/missionaries-cannibals.pl +12 -2
  60. package/examples/check/modal-logic-kripke.pl +2 -1
  61. package/examples/check/observability-log-correlation.pl +1 -1
  62. package/examples/check/odrl-dpv-healthcare-risk-ranked.pl +1 -1
  63. package/examples/check/odrl-dpv-risk-ranked.pl +1 -1
  64. package/examples/check/odrl-policy-reasoning.pl +40 -2
  65. package/examples/check/partial-evaluator.pl +7 -1
  66. package/examples/check/path-discovery.pl +7 -1
  67. package/examples/check/pell-equation.pl +1 -1
  68. package/examples/check/prime-range.pl +3 -2
  69. package/examples/check/propositional-dynamic-logic.pl +7 -2
  70. package/examples/check/quine-mccluskey.pl +21 -3
  71. package/examples/check/rdf12-annotated-claims.pl +1 -1
  72. package/examples/check/register-allocation.pl +2 -1
  73. package/examples/check/reified-conditionals.pl +4 -1
  74. package/examples/check/riemann-hypothesis.pl +4 -1
  75. package/examples/check/sat-solver-dpll.pl +1 -1
  76. package/examples/check/sbom-vulnerability-response.pl +4 -1
  77. package/examples/check/scientific-evidence-graph.pl +2 -1
  78. package/examples/check/send-more-money.pl +1 -1
  79. package/examples/check/sieve.pl +1 -1
  80. package/examples/check/snaf.pl +1 -1
  81. package/examples/check/stable-marriage.pl +2 -2
  82. package/examples/check/stirling-bell-numbers.pl +4 -1
  83. package/examples/check/superdense-coding.pl +8 -1
  84. package/examples/check/symbiotic-knowledge-graph.pl +14 -2
  85. package/examples/check/term-tools.pl +1 -1
  86. package/examples/check/totient-summatory.pl +4 -1
  87. package/examples/check/universal-vs-existential-termination.pl +1 -1
  88. package/examples/check/vanilla-meta-interpreter.pl +2 -1
  89. package/examples/check/weighted-interval-scheduling.pl +9 -2
  90. package/examples/check/wolf-goat-cabbage.pl +12 -1
  91. package/examples/check/workplace-compliance.pl +2 -1
  92. package/examples/evidence-demand-authority.pl +103 -0
  93. package/examples/output/evidence-demand-authority.pl +4 -0
  94. package/examples/proof/evidence-demand-authority.pl +53 -0
  95. package/package.json +1 -1
  96. package/playground.html +1 -0
  97. package/src/check-proof.js +18 -13
  98. package/src/cli.js +3 -1
  99. package/the-art-of-eyeprolog.md +276 -243
@@ -3,8 +3,15 @@ condition('C2', well_founded, ok, 84).
3
3
  condition('C3', justification, ok, 84).
4
4
  condition('C4', coverage, ok, 158).
5
5
  condition('C5', re_decision, ok, 38).
6
- obligation(absent, theory_scoped, 4).
7
- obligation(builtin, theory_scoped, 5).
6
+ obligation(absent, theory_scoped, \+ (interval(K, Startk, _finishk, _valuek), K > 8, Startk >= 11)).
7
+ obligation(absent, theory_scoped, \+ (interval(K, Startk, _finishk, _valuek), K > 7, Startk >= 10)).
8
+ obligation(absent, theory_scoped, \+ (interval(K, Startk, _finishk, _valuek), K > 6, Startk >= 9)).
9
+ obligation(absent, theory_scoped, \+ (interval(K, Startk, _finishk, _valuek), K > 5, Startk >= 9)).
10
+ obligation(builtin, theory_scoped, aggregate_min(Value, Value, (interval(Value, Startk, _finishk, _valuek), Value > 4, Startk >= 7), 8, 8)).
11
+ obligation(builtin, theory_scoped, aggregate_min(Value, Value, (interval(Value, Startk, _finishk, _valuek), Value > 3, Startk >= 6), 7, 7)).
12
+ obligation(builtin, theory_scoped, aggregate_min(Value, Value, (interval(Value, Startk, _finishk, _valuek), Value > 2, Startk >= 5), 6, 6)).
13
+ obligation(builtin, theory_scoped, aggregate_min(Value, Value, (interval(Value, Startk, _finishk, _valuek), Value > 1, Startk >= 4), 4, 4)).
14
+ obligation(builtin, theory_scoped, countall(interval(_i, _start, _finish, _value), 8)).
8
15
  steps(84).
9
16
  verified(37).
10
17
  recomputed(38).
@@ -3,7 +3,18 @@ condition('C2', well_founded, ok, 62).
3
3
  condition('C3', justification, ok, 62).
4
4
  condition('C4', coverage, ok, 94).
5
5
  condition('C5', re_decision, ok, 2).
6
- obligation(absent, theory_scoped, 12).
6
+ obligation(absent, theory_scoped, \+ member("ewew", ["wwww"])).
7
+ obligation(absent, theory_scoped, \+ member("wwew", ["ewew", "wwww"])).
8
+ obligation(absent, theory_scoped, \+ member("eeew", ["wwew", "ewew", "wwww"])).
9
+ obligation(absent, theory_scoped, \+ member("weww", ["eeew", "wwew", "ewew", "wwww"])).
10
+ obligation(absent, theory_scoped, \+ member("eewe", ["weww", "eeew", "wwew", "ewew", "wwww"])).
11
+ obligation(absent, theory_scoped, \+ member("wewe", ["eewe", "weww", "eeew", "wwew", "ewew", "wwww"])).
12
+ obligation(absent, theory_scoped, \+ member("eeee", ["wewe", "eewe", "weww", "eeew", "wwew", "ewew", "wwww"])).
13
+ obligation(absent, theory_scoped, \+ member("ewee", ["wwew", "ewew", "wwww"])).
14
+ obligation(absent, theory_scoped, \+ member("wwwe", ["ewee", "wwew", "ewew", "wwww"])).
15
+ obligation(absent, theory_scoped, \+ member("eewe", ["wwwe", "ewee", "wwew", "ewew", "wwww"])).
16
+ obligation(absent, theory_scoped, \+ member("wewe", ["eewe", "wwwe", "ewee", "wwew", "ewew", "wwww"])).
17
+ obligation(absent, theory_scoped, \+ member("eeee", ["wewe", "eewe", "wwwe", "ewee", "wwew", "ewew", "wwww"])).
7
18
  steps(62).
8
19
  verified(48).
9
20
  recomputed(2).
@@ -3,7 +3,8 @@ condition('C2', well_founded, ok, 15).
3
3
  condition('C3', justification, ok, 15).
4
4
  condition('C4', coverage, ok, 15).
5
5
  condition('C5', re_decision, ok, 0).
6
- obligation(absent, theory_scoped, 2).
6
+ obligation(absent, theory_scoped, \+ does(alice, work_related_task)).
7
+ obligation(absent, theory_scoped, \+ does(dave, log_off_at_end_of_shift)).
7
8
  steps(15).
8
9
  verified(13).
9
10
  recomputed(0).
@@ -0,0 +1,103 @@
1
+ % An authority demands evidence, then withdraws the demand as one it was never
2
+ % permitted to make. Three questions survive the withdrawal, and none of them
3
+ % is answered by "never mind": was the status ever at risk, may the missed
4
+ % deadline count against the holder, and what becomes of evidence that was
5
+ % handed over while the demand still looked binding?
6
+ %
7
+ % The case is modelled so that each of those is a separate query with its own
8
+ % derivation, because they have different answers. Withdrawing a demand settles
9
+ % the first. It does not by itself settle the other two.
10
+ %
11
+ % The reasoning rests on one distinction the engine takes seriously elsewhere:
12
+ % not proving something is not the same as disproving it. The holder never
13
+ % showed they still met the conditions. That is not a finding that they did
14
+ % not, and a ground for termination needs the finding, not the silence.
15
+
16
+ :- dynamic(breached/2).
17
+
18
+ %% ?- demand_validity(X0, X1).
19
+
20
+ %% ?- termination_ground(X0, X1).
21
+
22
+ %% ?- admissible(X0, X1).
23
+
24
+ %% ?- holder_status(X0, X1).
25
+
26
+
27
+ % What the authority may ask for at all. A power is granted for a purpose; a
28
+ % demand outside it is not a weaker demand, it is not a demand.
29
+ may_demand(authority, evidence_of(criminal_record)).
30
+ may_demand(authority, evidence_of(identity)).
31
+
32
+ % What was actually demanded, and under what deadline.
33
+ demanded(authority, holder, evidence_of(continued_conditions), deadline(30)).
34
+ withdrawn(authority, evidence_of(continued_conditions), reason(not_permitted_to_ask)).
35
+
36
+ % What happened. The holder let the deadline pass, and separately had already
37
+ % sent one document while the demand still appeared to bind.
38
+ elapsed(deadline(30)).
39
+ produced(holder, document(tenancy_record), under(evidence_of(continued_conditions))).
40
+
41
+ % The conditions of the status itself, and what is actually known about them.
42
+ condition_of_status(lawful_residence).
43
+ condition_of_status(no_relevant_conviction).
44
+
45
+ % Breaches are recorded here. The relation is declared and empty: no breach is
46
+ % known. Declaring it says that much -- asking whether a breach is recorded is
47
+ % a question with an answer, and the answer is no. Leaving it undeclared would
48
+ % instead make the question an error, which is a different thing from silence.
49
+
50
+
51
+ % A demand is valid only if it falls within a granted power.
52
+ demand_validity(Subject, valid) :-
53
+ demanded(authority, _, Subject, _),
54
+ may_demand(authority, Subject).
55
+
56
+ demand_validity(Subject, invalid(outside_granted_power)) :-
57
+ demanded(authority, _, Subject, _),
58
+ \+ may_demand(authority, Subject).
59
+
60
+
61
+ % A missed deadline is a ground for termination only when the demand it
62
+ % attached to was one the authority could make. Against an invalid demand the
63
+ % silence carries nothing, whether or not the demand was later withdrawn --
64
+ % the withdrawal records the defect, it does not create it.
65
+ termination_ground(missed_deadline(Subject), available) :-
66
+ demanded(authority, holder, Subject, Deadline),
67
+ elapsed(Deadline),
68
+ demand_validity(Subject, valid).
69
+
70
+ termination_ground(missed_deadline(Subject), unavailable(demand_was_invalid)) :-
71
+ demanded(authority, holder, Subject, Deadline),
72
+ elapsed(Deadline),
73
+ demand_validity(Subject, invalid(_)).
74
+
75
+ % A breach of an actual condition would be a ground. None is recorded, and the
76
+ % absence of a record is not a breach, so this rule derives nothing here. It is
77
+ % written out so the proof shows which ground was looked for and not found.
78
+ termination_ground(breach(Condition), available) :-
79
+ condition_of_status(Condition),
80
+ breached(holder, Condition).
81
+
82
+
83
+ % Evidence handed over under a demand that could not be made does not become
84
+ % usable because it was handed over. The defect is in the asking, so it reaches
85
+ % everything the asking produced.
86
+ admissible(document(D), no(obtained_under_invalid_demand)) :-
87
+ produced(holder, document(D), under(Subject)),
88
+ demand_validity(Subject, invalid(_)).
89
+
90
+ admissible(document(D), yes) :-
91
+ produced(holder, document(D), under(Subject)),
92
+ demand_validity(Subject, valid).
93
+
94
+
95
+ % The status stands unless some ground for ending it is available.
96
+ holder_status(status, retained) :-
97
+ \+ available_ground.
98
+
99
+ holder_status(status, terminated) :-
100
+ available_ground.
101
+
102
+ available_ground :-
103
+ termination_ground(_, available).
@@ -0,0 +1,4 @@
1
+ demand_validity(evidence_of(continued_conditions), invalid(outside_granted_power)).
2
+ termination_ground(missed_deadline(evidence_of(continued_conditions)), unavailable(demand_was_invalid)).
3
+ admissible(document(tenancy_record), no(obtained_under_invalid_demand)).
4
+ holder_status(status, retained).
@@ -0,0 +1,53 @@
1
+ demand_validity(evidence_of(continued_conditions), invalid(outside_granted_power)).
2
+ termination_ground(missed_deadline(evidence_of(continued_conditions)), unavailable(demand_was_invalid)).
3
+ admissible(document(tenancy_record), no(obtained_under_invalid_demand)).
4
+ holder_status(status, retained).
5
+
6
+ clause(4, demanded(authority, holder, evidence_of(continued_conditions), deadline(30)), true).
7
+ clause(6, elapsed(deadline(30)), true).
8
+ clause(7,
9
+ produced(holder, document(tenancy_record), under(evidence_of(continued_conditions))),
10
+ true).
11
+ clause(11,
12
+ demand_validity(var('Subject'), invalid(outside_granted_power)),
13
+ (demanded(authority, anonymous(1), var('Subject'), anonymous(2)),
14
+ \+ may_demand(authority, var('Subject')))).
15
+ clause(13,
16
+ termination_ground(missed_deadline(var('Subject')), unavailable(demand_was_invalid)),
17
+ (demanded(authority, holder, var('Subject'), var('Deadline')),
18
+ elapsed(var('Deadline')),
19
+ demand_validity(var('Subject'), invalid(anonymous(1))))).
20
+ clause(15,
21
+ admissible(document(var('D')), no(obtained_under_invalid_demand)),
22
+ (produced(holder, document(var('D')), under(var('Subject'))),
23
+ demand_validity(var('Subject'), invalid(anonymous(1))))).
24
+ clause(17, holder_status(status, retained), \+ available_ground).
25
+
26
+ step(demand_validity(evidence_of(continued_conditions), invalid(outside_granted_power)),
27
+ rule(11),
28
+ ['Subject' = evidence_of(continued_conditions)],
29
+ [demanded(authority, holder, evidence_of(continued_conditions), deadline(30)),
30
+ \+ may_demand(authority, evidence_of(continued_conditions))]).
31
+ step(demanded(authority, holder, evidence_of(continued_conditions), deadline(30)),
32
+ fact(4),
33
+ [],
34
+ []).
35
+ step(\+ may_demand(authority, evidence_of(continued_conditions)), absent, [], []).
36
+ step(termination_ground(missed_deadline(evidence_of(continued_conditions)), unavailable(demand_was_invalid)),
37
+ rule(13),
38
+ ['Subject' = evidence_of(continued_conditions), 'Deadline' = deadline(30)],
39
+ [demanded(authority, holder, evidence_of(continued_conditions), deadline(30)),
40
+ elapsed(deadline(30)),
41
+ demand_validity(evidence_of(continued_conditions), invalid(outside_granted_power))]).
42
+ step(elapsed(deadline(30)), fact(6), [], []).
43
+ step(admissible(document(tenancy_record), no(obtained_under_invalid_demand)),
44
+ rule(15),
45
+ ['D' = tenancy_record, 'Subject' = evidence_of(continued_conditions)],
46
+ [produced(holder, document(tenancy_record), under(evidence_of(continued_conditions))),
47
+ demand_validity(evidence_of(continued_conditions), invalid(outside_granted_power))]).
48
+ step(produced(holder, document(tenancy_record), under(evidence_of(continued_conditions))),
49
+ fact(7),
50
+ [],
51
+ []).
52
+ step(holder_status(status, retained), rule(17), [], [\+ available_ground]).
53
+ step(\+ available_ground, absent, [], []).
package/package.json CHANGED
@@ -3,7 +3,7 @@
3
3
  "publishConfig": {
4
4
  "access": "public"
5
5
  },
6
- "version": "1.6.19",
6
+ "version": "1.6.21",
7
7
  "description": "EyeProlog turns facts and rules into answers and proofs.",
8
8
  "type": "module",
9
9
  "main": "./index.js",
package/playground.html CHANGED
@@ -522,6 +522,7 @@
522
522
  "equivalence-classes-overlap-implies-same-class",
523
523
  "eulerian-path",
524
524
  "ev-range-worlds",
525
+ "evidence-demand-authority",
525
526
  "existential-rule",
526
527
  "exoplanet-validation-worlds",
527
528
  "explainable-ev-depot-configuration",
@@ -39,6 +39,7 @@
39
39
  import { ATOM, COMPOUND, Env, compareTerms, copyResolved, freshTerm, properListItems, termToString, unify } from './term.js';
40
40
  import { parseProgramText } from './parser.js';
41
41
  import { clauseNumbering } from './explain.js';
42
+ import { formatTermForWrite } from './write.js';
42
43
  import { Program, autoloadProgramGoals } from './program.js';
43
44
  import { Solver } from './solver.js';
44
45
 
@@ -345,7 +346,7 @@ export function checkProofDocument(program, text) {
345
346
  if (REDECIDED.has(justification.kind)) {
346
347
  const reason = notRedecidableReason(step.conclusion);
347
348
  if (reason) {
348
- trusted.push({ kind: justification.kind, conclusion: key(step.conclusion), reason });
349
+ trusted.push({ kind: justification.kind, conclusion: key(step.conclusion), term: step.conclusion, reason });
349
350
  continue;
350
351
  }
351
352
  const outcome = redecide(step.conclusion);
@@ -376,12 +377,12 @@ export function checkProofDocument(program, text) {
376
377
  continue;
377
378
  }
378
379
  // Nothing was learned about this step, so it is still an obligation.
379
- trusted.push({ kind: justification.kind, conclusion: key(step.conclusion), reason: 'theory_scoped' });
380
+ trusted.push({ kind: justification.kind, conclusion: key(step.conclusion), term: step.conclusion, reason: 'theory_scoped' });
380
381
  }
381
382
  continue;
382
383
  }
383
384
  if (TRUSTED.has(justification.kind)) {
384
- trusted.push({ kind: justification.kind, conclusion: key(step.conclusion) });
385
+ trusted.push({ kind: justification.kind, conclusion: key(step.conclusion), term: step.conclusion });
385
386
  continue;
386
387
  }
387
388
 
@@ -429,6 +430,8 @@ export function checkProofDocument(program, text) {
429
430
  ];
430
431
 
431
432
  return {
433
+ writeOptions: { doubleQuotes: program?.doubleQuotes ?? 'chars', doubleBar: true, quoted: true,
434
+ operators: [...(program?.operators?.values() ?? [])] },
432
435
  valid: failures.length === 0,
433
436
  steps: steps.length,
434
437
  verified,
@@ -454,7 +457,9 @@ export function checkProofDocument(program, text) {
454
457
  // steps/1 verified/1 recomputed/1 trusted/1 claims/1
455
458
  // verdict(checked | checked_with_obligations | failed(N))
456
459
  export function checkReportTerms(report) {
457
- const options = { quoted: true };
460
+ // Write terms the way the proof under check writes them, so `\\+ G` is not
461
+ // spelled `'\\\\+'(G)` here and the two documents stay comparable by eye.
462
+ const options = report.writeOptions ?? { quoted: true };
458
463
  const out = [];
459
464
  const say = (line) => out.push(line);
460
465
 
@@ -465,20 +470,20 @@ export function checkReportTerms(report) {
465
470
 
466
471
  for (const failure of report.failures ?? []) {
467
472
  const conclusion = failure.term != null
468
- ? termToString(failure.term, new Env(), true, options)
473
+ ? formatTermForWrite(failure.term, new Env(), options)
469
474
  : quotedAtom(failure.conclusion);
470
475
  say(`failure('${failure.condition}', ${conclusion}, ${quotedAtom(failure.detail)}).`);
471
476
  }
472
477
 
473
- const groups = new Map();
478
+ // One fact per obligation, naming the conclusion itself. A count would say
479
+ // how much the check rests on without saying what, and what it rests on is
480
+ // the part a reader -- or a later program -- has to weigh. The total is in
481
+ // trusted/1 below.
474
482
  for (const item of report.trusted ?? []) {
475
- const reason = item.reason ?? 'theory_scoped';
476
- const groupKey = `${item.kind}\u0000${reason}`;
477
- groups.set(groupKey, (groups.get(groupKey) ?? 0) + 1);
478
- }
479
- for (const [groupKey, count] of groups) {
480
- const [kind, reason] = groupKey.split('\u0000');
481
- say(`obligation(${kind}, ${reason}, ${count}).`);
483
+ const conclusion = item.term != null
484
+ ? formatTermForWrite(item.term, new Env(), options)
485
+ : quotedAtom(item.conclusion);
486
+ say(`obligation(${item.kind}, ${item.reason ?? 'theory_scoped'}, ${conclusion}).`);
482
487
  }
483
488
 
484
489
  say(`steps(${report.steps}).`);
package/src/cli.js CHANGED
@@ -422,7 +422,9 @@ Options:
422
422
  that calls a library. (implies --proof)
423
423
  --check-proof file Check a saved proof document against the input program
424
424
  and write the result as Prolog facts: condition/4 per
425
- condition, failure/3, obligation/3, and verdict/1.
425
+ condition, failure/3 for what did not hold, one
426
+ obligation/3 naming each conclusion the check rests on,
427
+ and verdict/1.
426
428
  Use - to read the proof from stdin, for example
427
429
  eyeprolog --proof p.pl | eyeprolog --check-proof - p.pl
428
430
  -q, --quads Run embedded quad tests and fail if any do not hold.