eyeprolog 1.4.6 → 1.4.7
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/examples/deck/README.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
Wide-audience companion explanations for selected runnable examples.
|
|
4
4
|
|
|
5
|
-
- [Introduction to EyeProlog](https://eyereasoner.github.io/eyeprolog/examples/deck/introduction-to-eyeprolog) — a
|
|
5
|
+
- [Introduction to EyeProlog](https://eyereasoner.github.io/eyeprolog/examples/deck/introduction-to-eyeprolog) — a guided slide deck introducing facts, rules, answers, proofs, CLP(Z), CLP(B), ISO conformance, JavaScript embedding, RDF roundtrips, and a categorized path through the example corpus.
|
|
6
6
|
- [Cross-organization data sharing](https://eyereasoner.github.io/eyeprolog/examples/deck/cross-organization-data-sharing) — ODRL/DPV sharing decisions with permit, deny, review, safeguards, and obligations.
|
|
7
7
|
- [Explainable EV-depot configuration](https://eyereasoner.github.io/eyeprolog/examples/deck/explainable-ev-depot-configuration) — reversible configuration rules that select a charger, explain blockers, and derive required changes.
|
|
8
8
|
- [ODRL policy reasoning](https://eyereasoner.github.io/eyeprolog/examples/deck/odrl-policy-reasoning) — permissions, prohibitions, duties, conflicts, and defaults.
|
|
@@ -1,26 +1,24 @@
|
|
|
1
1
|
---
|
|
2
2
|
marp: true
|
|
3
3
|
title: Introduction to EyeProlog
|
|
4
|
-
description: A short presentation introducing EyeProlog as a portable, inspectable ISO Prolog engine for answers, proofs, and RDF-backed reasoning.
|
|
4
|
+
description: A short presentation introducing EyeProlog as a portable, inspectable ISO Prolog engine for answers, proofs, constraints, and RDF-backed reasoning.
|
|
5
5
|
---
|
|
6
6
|
|
|
7
7
|
# Introduction to EyeProlog
|
|
8
8
|
|
|
9
|
-
Portable Prolog reasoning for answers, proofs, and knowledge graphs
|
|
9
|
+
Portable Prolog reasoning for answers, proofs, constraints, and knowledge graphs
|
|
10
|
+
|
|
11
|
+
EyeProlog is meant to be approachable from two directions at once: it is small enough to embed in JavaScript applications, yet explicit enough that a conclusion can be explained as ordinary facts and rules.
|
|
10
12
|
|
|
11
13
|
---
|
|
12
14
|
|
|
13
15
|
## What is EyeProlog?
|
|
14
16
|
|
|
15
|
-
EyeProlog is
|
|
17
|
+
EyeProlog is an ISO-oriented Prolog implementation for JavaScript.
|
|
16
18
|
|
|
17
|
-
It turns explicit facts and rules into
|
|
19
|
+
It turns explicit facts and rules into answers, variable bindings, checked example output, optional proof traces, and embeddable reasoning in Node.js or browsers.
|
|
18
20
|
|
|
19
|
-
-
|
|
20
|
-
- variable bindings;
|
|
21
|
-
- checked example output;
|
|
22
|
-
- optional proof traces;
|
|
23
|
-
- embeddable reasoning in Node.js and browsers.
|
|
21
|
+
The project’s emphasis is not only “can this query run?” but also “can we inspect what happened, test it again, and explain why the answer follows?” That makes EyeProlog useful for demos, documentation, knowledge-graph workflows, and applications that need a small transparent reasoning layer.
|
|
24
22
|
|
|
25
23
|
---
|
|
26
24
|
|
|
@@ -42,6 +40,8 @@ Then you ask questions:
|
|
|
42
40
|
true.
|
|
43
41
|
```
|
|
44
42
|
|
|
43
|
+
The same rule can answer a yes/no question, enumerate solutions, or participate in a larger proof. That reuse is one of the reasons Prolog remains attractive for rule-heavy software.
|
|
44
|
+
|
|
45
45
|
---
|
|
46
46
|
|
|
47
47
|
## The core idea
|
|
@@ -56,7 +56,9 @@ facts + rules + query
|
|
|
56
56
|
answers with reasons
|
|
57
57
|
```
|
|
58
58
|
|
|
59
|
-
|
|
59
|
+
A query is not just a function call. It is a logical request: “find values that make this relation true.” EyeProlog searches by unifying terms, trying clauses, and backtracking over alternatives.
|
|
60
|
+
|
|
61
|
+
Because the input remains ordinary Prolog text, the boundary between data, rules, and answers stays inspectable.
|
|
60
62
|
|
|
61
63
|
---
|
|
62
64
|
|
|
@@ -78,6 +80,8 @@ Try a list query:
|
|
|
78
80
|
; X = logic.
|
|
79
81
|
```
|
|
80
82
|
|
|
83
|
+
The semicolon asks for another answer. This small interaction already shows the Prolog execution model: a relation can produce more than one solution.
|
|
84
|
+
|
|
81
85
|
---
|
|
82
86
|
|
|
83
87
|
## Programs are ordinary text
|
|
@@ -97,6 +101,8 @@ Run it:
|
|
|
97
101
|
eyeprolog examples/socrates.pl
|
|
98
102
|
```
|
|
99
103
|
|
|
104
|
+
The examples directory uses this same pattern at larger scale. Each runnable example has checked output, so examples are not just illustrative snippets; they are part of the release gate.
|
|
105
|
+
|
|
100
106
|
---
|
|
101
107
|
|
|
102
108
|
## Proofs are first-class
|
|
@@ -107,12 +113,9 @@ EyeProlog can show not only *what* was concluded, but *why*.
|
|
|
107
113
|
eyeprolog --proof examples/socrates.pl
|
|
108
114
|
```
|
|
109
115
|
|
|
110
|
-
Proof output is useful for
|
|
116
|
+
Proof output is useful for debugging rules, explaining decisions, preserving audit trails, and keeping documentation honest. If a proof-producing example changes, the checked proof output changes too.
|
|
111
117
|
|
|
112
|
-
|
|
113
|
-
- explaining decisions;
|
|
114
|
-
- regression tests;
|
|
115
|
-
- audit trails.
|
|
118
|
+
This is especially helpful when rules encode policies, risk decisions, or derived knowledge where the explanation matters as much as the final answer.
|
|
116
119
|
|
|
117
120
|
---
|
|
118
121
|
|
|
@@ -120,23 +123,44 @@ Proof output is useful for:
|
|
|
120
123
|
|
|
121
124
|
EyeProlog starts from ISO/IEC 13211-1 Prolog.
|
|
122
125
|
|
|
123
|
-
That matters because facts, rules, terms, control, errors, streams, arithmetic, and meta-calls have an external reference point.
|
|
126
|
+
That matters because facts, rules, terms, control, errors, streams, arithmetic, and meta-calls have an external reference point. Strict ISO mode keeps that standardized core separate and testable.
|
|
127
|
+
|
|
128
|
+
Normal mode adds practical libraries and embedding features. The design goal is to keep extensions visible rather than hiding them inside an undocumented dialect.
|
|
129
|
+
|
|
130
|
+
---
|
|
131
|
+
|
|
132
|
+
## Constraints over integers: CLP(Z)
|
|
124
133
|
|
|
125
|
-
|
|
134
|
+
`library(clpz)` lets programs state relations over integers instead of manually enumerating arithmetic cases.
|
|
135
|
+
|
|
136
|
+
```prolog
|
|
137
|
+
:- use_module(library(clpz)).
|
|
138
|
+
|
|
139
|
+
?- X #>= 1, X #=< 4, Y #= X*X, labeling([X]).
|
|
140
|
+
X = 1, Y = 1
|
|
141
|
+
; X = 2, Y = 4
|
|
142
|
+
; X = 3, Y = 9
|
|
143
|
+
; X = 4, Y = 16.
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
This style is useful when you know the constraints before you know the values: scheduling, allocation, Sudoku, finite-domain puzzles, resource planning, and arithmetic search.
|
|
126
147
|
|
|
127
148
|
---
|
|
128
149
|
|
|
129
|
-
##
|
|
150
|
+
## Constraints over Booleans: CLP(B)
|
|
130
151
|
|
|
131
|
-
|
|
152
|
+
`library(clpb)` provides Boolean constraints with satisfiability, cardinality, counting, and optimization predicates.
|
|
153
|
+
|
|
154
|
+
```prolog
|
|
155
|
+
:- use_module(library(clpb)).
|
|
156
|
+
|
|
157
|
+
?- sat(card([2], [A,B,C,D]) * (A =< C) * (B # D)),
|
|
158
|
+
labeling([A,B,C,D]).
|
|
159
|
+
```
|
|
132
160
|
|
|
133
|
-
|
|
134
|
-
- npm packages;
|
|
135
|
-
- browser playgrounds;
|
|
136
|
-
- web workers;
|
|
137
|
-
- JavaScript APIs.
|
|
161
|
+
The recent CLP(B) examples show several practical shapes: circuit verification, quorum constraints, feature-model counting, and weighted release planning.
|
|
138
162
|
|
|
139
|
-
|
|
163
|
+
Boolean constraints are compact when the domain is “on/off”, “selected/not selected”, “permitted/denied”, or “feature enabled/disabled”.
|
|
140
164
|
|
|
141
165
|
---
|
|
142
166
|
|
|
@@ -154,56 +178,79 @@ RDF dataset
|
|
|
154
178
|
|
|
155
179
|
RDF remains the interchange layer. Prolog remains the transparent reasoning layer.
|
|
156
180
|
|
|
181
|
+
This is useful when a knowledge graph needs explicit derivation rules, but the data should still move in and out as RDF rather than as a private in-memory structure.
|
|
182
|
+
|
|
157
183
|
---
|
|
158
184
|
|
|
159
|
-
##
|
|
185
|
+
## Categorized examples: start here
|
|
160
186
|
|
|
161
|
-
The example
|
|
187
|
+
The example corpus is intentionally broad. A practical path through it is:
|
|
162
188
|
|
|
163
|
-
-
|
|
164
|
-
-
|
|
165
|
-
-
|
|
166
|
-
-
|
|
167
|
-
-
|
|
168
|
-
- symbiotic
|
|
189
|
+
- **First steps:** `socrates.pl`, `ancestor.pl`, `list-collection.pl`.
|
|
190
|
+
- **Algorithms:** graph reachability, Dijkstra, parser, FFT, SAT/DPLL.
|
|
191
|
+
- **Integer constraints:** CLP(Z) queens, Sudoku, resource allocation.
|
|
192
|
+
- **Boolean constraints:** CLP(B) circuits, cardinality, feature models, planning.
|
|
193
|
+
- **Policies and decisions:** access control, ODRL, GDPR, trust flow.
|
|
194
|
+
- **RDF roundtrips:** symbiotic knowledge graph and domain-specific RDF scenarios.
|
|
195
|
+
- **Proofs:** examples with checked `--proof` output.
|
|
169
196
|
|
|
170
|
-
|
|
197
|
+
Use the [playground](https://eyereasoner.github.io/eyeprolog/playground) for quick exploration, or browse the [examples source tree](https://github.com/eyereasoner/eyeprolog/tree/main/examples) when you want to inspect the program and golden output side by side.
|
|
171
198
|
|
|
172
199
|
---
|
|
173
200
|
|
|
174
|
-
##
|
|
201
|
+
## Example path: constraints
|
|
202
|
+
|
|
203
|
+
For constraint reasoning, start with the small examples and move outward:
|
|
204
|
+
|
|
205
|
+
- `clpz-n-queens.pl` shows finite-domain search.
|
|
206
|
+
- `clpz-sudoku-9x9.pl` shows a familiar grid problem.
|
|
207
|
+
- `clpz-resource-allocation.pl` shows planning under resource limits.
|
|
208
|
+
- `clpb-boolean-circuit.pl` shows Boolean verification.
|
|
209
|
+
- `clpb-cardinality.pl` shows exact-count selection.
|
|
210
|
+
- `clpb-feature-model.pl` and `clpb-weighted-planning.pl` show product/release decisions.
|
|
211
|
+
|
|
212
|
+
Together these examples show that Prolog can describe a problem declaratively while constraint libraries do the propagation and search work.
|
|
213
|
+
|
|
214
|
+
---
|
|
215
|
+
|
|
216
|
+
## Example path: knowledge graphs
|
|
217
|
+
|
|
218
|
+
For RDF-backed reasoning, start with [Symbiotic Knowledge Graphs](https://eyereasoner.github.io/eyeprolog/examples/deck/symbiotic-knowledge-graphs).
|
|
175
219
|
|
|
176
|
-
|
|
220
|
+
Then explore the scenario decks:
|
|
177
221
|
|
|
178
|
-
-
|
|
179
|
-
-
|
|
180
|
-
-
|
|
181
|
-
-
|
|
182
|
-
-
|
|
183
|
-
|
|
184
|
-
|
|
222
|
+
- [Cross-organization data sharing](https://eyereasoner.github.io/eyeprolog/examples/deck/cross-organization-data-sharing)
|
|
223
|
+
- [Explainable EV-depot configuration](https://eyereasoner.github.io/eyeprolog/examples/deck/explainable-ev-depot-configuration)
|
|
224
|
+
- [Operational incident response](https://eyereasoner.github.io/eyeprolog/examples/deck/operational-incident-response)
|
|
225
|
+
- [SBOM vulnerability response](https://eyereasoner.github.io/eyeprolog/examples/deck/sbom-vulnerability-response)
|
|
226
|
+
- [Scientific evidence graph](https://eyereasoner.github.io/eyeprolog/examples/deck/scientific-evidence-graph)
|
|
227
|
+
|
|
228
|
+
Each scenario keeps source RDF, Prolog rules, generated Prolog, and output RDF as separate artifacts.
|
|
229
|
+
|
|
230
|
+
---
|
|
231
|
+
|
|
232
|
+
## Testing and conformance
|
|
233
|
+
|
|
234
|
+
EyeProlog’s release gate includes conformance cases, strict ISO tests, WG17 syntax cases, regression tests, runnable examples, proof examples, and documentation synchronization checks.
|
|
185
235
|
|
|
186
236
|
The point is simple: behavior should be reproducible, not anecdotal.
|
|
187
237
|
|
|
238
|
+
The examples are also linted for avoidable singleton-variable warnings. This keeps example code clean for users who run examples through stricter tooling or compare with other Prolog systems.
|
|
239
|
+
|
|
188
240
|
---
|
|
189
241
|
|
|
190
242
|
## When EyeProlog fits
|
|
191
243
|
|
|
192
|
-
EyeProlog is a good fit when a project needs
|
|
244
|
+
EyeProlog is a good fit when a project needs explicit rules, inspectable conclusions, portable Prolog syntax, an embeddable JavaScript runtime, checked examples and proofs, and a clean boundary between data, rules, and results.
|
|
193
245
|
|
|
194
|
-
-
|
|
195
|
-
- inspectable conclusions;
|
|
196
|
-
- portable Prolog syntax;
|
|
197
|
-
- embeddable JavaScript runtime;
|
|
198
|
-
- checked examples and proofs;
|
|
199
|
-
- a clean boundary between data, rules, and results.
|
|
246
|
+
It is not trying to replace high-performance native Prolog systems. Its niche is transparent reasoning that can live close to JavaScript applications, documentation, and web-accessible demos.
|
|
200
247
|
|
|
201
248
|
---
|
|
202
249
|
|
|
203
250
|
## Where to go next
|
|
204
251
|
|
|
205
252
|
- Read [project README](https://github.com/eyereasoner/eyeprolog#readme) for setup and links.
|
|
206
|
-
- Read [Why EyeProlog?](https://eyereasoner.github.io/eyeprolog/why-eyeprolog) for the design motivation.
|
|
207
253
|
- Open [EyeProlog playground](https://eyereasoner.github.io/eyeprolog/playground) to run examples in a browser.
|
|
208
|
-
-
|
|
254
|
+
- Browse [runnable examples](https://github.com/eyereasoner/eyeprolog/tree/main/examples) by category or filename.
|
|
255
|
+
- Read [Why EyeProlog?](https://eyereasoner.github.io/eyeprolog/why-eyeprolog) for the design motivation.
|
|
209
256
|
- Read [The Art of EyeProlog](https://eyereasoner.github.io/eyeprolog/the-art-of-eyeprolog) for the full reference.
|
package/package.json
CHANGED
package/test/run-regression.mjs
CHANGED
|
@@ -4647,8 +4647,65 @@ child.stdin.write(\`consult(${consultedAtom}).\\n\`);
|
|
|
4647
4647
|
}
|
|
4648
4648
|
|
|
4649
4649
|
|
|
4650
|
+
|
|
4651
|
+
function topLevelRunnableExampleFiles() {
|
|
4652
|
+
const examplesDir = path.join(packageRoot, 'examples');
|
|
4653
|
+
return fs.readdirSync(examplesDir)
|
|
4654
|
+
.filter((name) => name.endsWith('.pl'))
|
|
4655
|
+
.sort()
|
|
4656
|
+
.map((name) => path.join(examplesDir, name));
|
|
4657
|
+
}
|
|
4658
|
+
|
|
4659
|
+
function visitTermVariables(term, counts, seen = new Set()) {
|
|
4660
|
+
if (term == null) return;
|
|
4661
|
+
if (term.type === 'var') {
|
|
4662
|
+
// The parser preserves identity for repeated source variables. Count every
|
|
4663
|
+
// occurrence so only variables that occur once syntactically are flagged.
|
|
4664
|
+
counts.set(term.name, (counts.get(term.name) ?? 0) + 1);
|
|
4665
|
+
return;
|
|
4666
|
+
}
|
|
4667
|
+
if (seen.has(term)) return;
|
|
4668
|
+
seen.add(term);
|
|
4669
|
+
if (term.type === 'compound') {
|
|
4670
|
+
for (const arg of term.args) visitTermVariables(arg, counts, seen);
|
|
4671
|
+
}
|
|
4672
|
+
}
|
|
4673
|
+
|
|
4674
|
+
function singletonVariableWarningsForClause(clause) {
|
|
4675
|
+
const counts = new Map();
|
|
4676
|
+
visitTermVariables(clause.head, counts);
|
|
4677
|
+
for (const goal of clause.body ?? []) visitTermVariables(goal, counts);
|
|
4678
|
+
return [...counts]
|
|
4679
|
+
.filter(([name, count]) => count === 1 && !String(name).startsWith('_'))
|
|
4680
|
+
.map(([name]) => name);
|
|
4681
|
+
}
|
|
4682
|
+
|
|
4683
|
+
function singletonVariableWarningsForRunnableExamples() {
|
|
4684
|
+
const warnings = [];
|
|
4685
|
+
for (const filename of topLevelRunnableExampleFiles()) {
|
|
4686
|
+
const text = fs.readFileSync(filename, 'utf8');
|
|
4687
|
+
const program = Program.parseSources([{ text, filename }], { sourceMetadata: true });
|
|
4688
|
+
for (const clause of program.clauses) {
|
|
4689
|
+
if (path.resolve(clause.source?.filename ?? '') !== path.resolve(filename)) continue;
|
|
4690
|
+
for (const name of singletonVariableWarningsForClause(clause)) {
|
|
4691
|
+
warnings.push(`singleton: ${name}, near ${path.relative(packageRoot, filename)}:${clause.source?.line ?? '?'}`);
|
|
4692
|
+
}
|
|
4693
|
+
}
|
|
4694
|
+
}
|
|
4695
|
+
return warnings;
|
|
4696
|
+
}
|
|
4697
|
+
|
|
4650
4698
|
function documentationSyncCases() {
|
|
4651
4699
|
return [
|
|
4700
|
+
{
|
|
4701
|
+
name: 'runnable examples are free of singleton-variable warnings',
|
|
4702
|
+
run: () => {
|
|
4703
|
+
const warnings = singletonVariableWarningsForRunnableExamples();
|
|
4704
|
+
if (warnings.length !== 0) {
|
|
4705
|
+
throw new Error(`example singleton-variable warnings\n${warnings.join('\n')}`);
|
|
4706
|
+
}
|
|
4707
|
+
},
|
|
4708
|
+
},
|
|
4652
4709
|
{
|
|
4653
4710
|
name: 'WG17 syntax status matches its executable-coverage manifest',
|
|
4654
4711
|
run: () => {
|