eyeling 1.13.2 → 1.13.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/HANDBOOK.md +2 -0
- package/examples/allen-interval-calculus.n3 +180 -0
- package/examples/deck/odrl-dpv-risk-ranked.md +251 -0
- package/examples/dining-philosophers.n3 +383 -0
- package/examples/input/annotation.ttl +3 -1
- package/examples/input/reifies.ttl +2 -0
- package/examples/input/triple-term.ttl +3 -2
- package/examples/kaprekar.n3 +205 -0
- package/examples/odrl-dpv-ehds-risk-ranked.n3 +473 -0
- package/examples/odrl-dpv-healthcare-risk-ranked.n3 +575 -0
- package/examples/odrl-dpv-risk-ranked.n3 +30 -31
- package/examples/output/allen-interval-calculus.n3 +157 -0
- package/examples/output/dining-philosophers.n3 +808 -0
- package/examples/output/kaprekar.n3 +9992 -0
- package/examples/output/odrl-dpv-ehds-risk-ranked.n3 +144 -0
- package/examples/output/odrl-dpv-healthcare-risk-ranked.n3 +117 -0
- package/examples/output/odrl-dpv-risk-ranked.n3 +70 -6
- package/examples/output/wind-turbine.n3 +6 -0
- package/examples/reifies.n3 +1 -2
- package/examples/triple-term.n3 +3 -3
- package/examples/wind-turbine.n3 +63 -0
- package/eyeling.js +7 -2
- package/lib/cli.js +4 -1
- package/lib/engine.js +3 -1
- package/package.json +1 -1
- package/test/api.test.js +11 -0
- package/tools/n3gen.js +36 -7
|
@@ -0,0 +1,383 @@
|
|
|
1
|
+
# ================================================================================
|
|
2
|
+
# Dining Philosophers — Chandy–Misra (dirty/clean forks + requests)
|
|
3
|
+
#
|
|
4
|
+
# What this file demonstrates:
|
|
5
|
+
# A concrete distributed-style run (9 rounds) where each of 5 philosophers
|
|
6
|
+
# eats exactly 3 times (15 meals total), using the classic Chandy–Misra idea:
|
|
7
|
+
#
|
|
8
|
+
# - Forks are shared resources held by exactly one endpoint at a time.
|
|
9
|
+
# - Each fork is either Dirty or Clean.
|
|
10
|
+
# - Hungry philosophers request any adjacent fork they do not hold.
|
|
11
|
+
# - A holder transfers a fork ONLY if it is Dirty (the "dirty fork" rule).
|
|
12
|
+
# - Upon transfer, the receiver has it Clean.
|
|
13
|
+
# - After eating, forks become Dirty again (in this trace, that makes all
|
|
14
|
+
# forks Dirty at the end of each round).
|
|
15
|
+
#
|
|
16
|
+
# About the "trace construction" in N3:
|
|
17
|
+
# N3 reasoning is monotonic and does not have a built-in closed-world "else".
|
|
18
|
+
# To build a deterministic next state without negation, the trace includes
|
|
19
|
+
# explicit dp:KeepFork facts for forks that are not transferred in that round.
|
|
20
|
+
# Transfers themselves are NOT asserted: they are derived from Requests + Dirty.
|
|
21
|
+
#
|
|
22
|
+
# What you can query in a reasoner:
|
|
23
|
+
# - Meals: ?m a dp:Meal .
|
|
24
|
+
# - Requests: ?r a dp:Request .
|
|
25
|
+
# - Transfers: ?t a dp:SendFork .
|
|
26
|
+
#
|
|
27
|
+
# Derived meals match the "realistic schedule" pattern:
|
|
28
|
+
# Round 1/4/7: P1 and P3 eat
|
|
29
|
+
# Round 2/5/8: P2 and P4 eat
|
|
30
|
+
# Round 3/6/9: P5 eats
|
|
31
|
+
# ================================================================================
|
|
32
|
+
|
|
33
|
+
@prefix dp: <http://example.org/dp#> .
|
|
34
|
+
@prefix log: <http://www.w3.org/2000/10/swap/log#> .
|
|
35
|
+
|
|
36
|
+
# ------------------
|
|
37
|
+
# Minimal vocabulary
|
|
38
|
+
# ------------------
|
|
39
|
+
|
|
40
|
+
dp:Philosopher a dp:Class .
|
|
41
|
+
dp:Fork a dp:Class .
|
|
42
|
+
dp:Slot a dp:Class .
|
|
43
|
+
dp:Config a dp:Class .
|
|
44
|
+
|
|
45
|
+
dp:ForkState a dp:Class .
|
|
46
|
+
dp:Request a dp:Class .
|
|
47
|
+
dp:SendFork a dp:Class .
|
|
48
|
+
dp:KeepFork a dp:Class .
|
|
49
|
+
dp:Meal a dp:Class .
|
|
50
|
+
dp:MealHandle a dp:Class .
|
|
51
|
+
|
|
52
|
+
dp:Dirty a dp:Cleanliness .
|
|
53
|
+
dp:Clean a dp:Cleanliness .
|
|
54
|
+
dp:Cleanliness a dp:Class .
|
|
55
|
+
|
|
56
|
+
dp:end1 a dp:Property .
|
|
57
|
+
dp:end2 a dp:Property .
|
|
58
|
+
|
|
59
|
+
dp:leftFork a dp:Property .
|
|
60
|
+
dp:rightFork a dp:Property .
|
|
61
|
+
|
|
62
|
+
dp:in a dp:Property . # state/action/message -> Config
|
|
63
|
+
dp:fork a dp:Property .
|
|
64
|
+
dp:holder a dp:Property .
|
|
65
|
+
dp:cleanliness a dp:Property .
|
|
66
|
+
|
|
67
|
+
dp:from a dp:Property .
|
|
68
|
+
dp:to a dp:Property .
|
|
69
|
+
|
|
70
|
+
dp:afterSends a dp:Property . # start-of-round Config -> after-transfer Config
|
|
71
|
+
dp:afterEat a dp:Property . # after-transfer Config -> end-of-round Config
|
|
72
|
+
|
|
73
|
+
dp:slot a dp:Property . # start-of-round Config -> Slot
|
|
74
|
+
dp:cycle a dp:Property . # start-of-round Config -> integer (meal number)
|
|
75
|
+
dp:hungry a dp:Property . # start-of-round Config -> Philosopher
|
|
76
|
+
|
|
77
|
+
dp:slotIndex a dp:Property . # Slot -> integer
|
|
78
|
+
|
|
79
|
+
dp:philosopher a dp:Property . # Meal -> Philosopher
|
|
80
|
+
dp:mealNo a dp:Property . # Meal -> integer
|
|
81
|
+
dp:inSlot a dp:Property . # Meal -> Slot
|
|
82
|
+
dp:usesFork a dp:Property . # Meal -> Fork
|
|
83
|
+
|
|
84
|
+
dp:meal a dp:Property . # MealHandle -> Meal
|
|
85
|
+
|
|
86
|
+
dp:ateTimes a dp:Property .
|
|
87
|
+
dp:Trace1 a dp:Thing .
|
|
88
|
+
dp:everyoneAteTimes3 a dp:Property .
|
|
89
|
+
|
|
90
|
+
# -------------------------------------------
|
|
91
|
+
# Topology: 5 philosophers, 5 forks in a ring
|
|
92
|
+
# -------------------------------------------
|
|
93
|
+
|
|
94
|
+
dp:P1 a dp:Philosopher .
|
|
95
|
+
dp:P2 a dp:Philosopher .
|
|
96
|
+
dp:P3 a dp:Philosopher .
|
|
97
|
+
dp:P4 a dp:Philosopher .
|
|
98
|
+
dp:P5 a dp:Philosopher .
|
|
99
|
+
|
|
100
|
+
dp:F12 a dp:Fork .
|
|
101
|
+
dp:F23 a dp:Fork .
|
|
102
|
+
dp:F34 a dp:Fork .
|
|
103
|
+
dp:F45 a dp:Fork .
|
|
104
|
+
dp:F51 a dp:Fork .
|
|
105
|
+
|
|
106
|
+
# Fork endpoints (ring)
|
|
107
|
+
dp:F12 dp:end1 dp:P1 ; dp:end2 dp:P2 .
|
|
108
|
+
dp:F23 dp:end1 dp:P2 ; dp:end2 dp:P3 .
|
|
109
|
+
dp:F34 dp:end1 dp:P3 ; dp:end2 dp:P4 .
|
|
110
|
+
dp:F45 dp:end1 dp:P4 ; dp:end2 dp:P5 .
|
|
111
|
+
dp:F51 dp:end1 dp:P5 ; dp:end2 dp:P1 .
|
|
112
|
+
|
|
113
|
+
# Choose a left/right convention around the ring
|
|
114
|
+
dp:P1 dp:leftFork dp:F51 ; dp:rightFork dp:F12 .
|
|
115
|
+
dp:P2 dp:leftFork dp:F12 ; dp:rightFork dp:F23 .
|
|
116
|
+
dp:P3 dp:leftFork dp:F23 ; dp:rightFork dp:F34 .
|
|
117
|
+
dp:P4 dp:leftFork dp:F34 ; dp:rightFork dp:F45 .
|
|
118
|
+
dp:P5 dp:leftFork dp:F45 ; dp:rightFork dp:F51 .
|
|
119
|
+
|
|
120
|
+
# ----------------
|
|
121
|
+
# Slots (9 rounds)
|
|
122
|
+
# ----------------
|
|
123
|
+
|
|
124
|
+
dp:s1 a dp:Slot ; dp:slotIndex 1 .
|
|
125
|
+
dp:s2 a dp:Slot ; dp:slotIndex 2 .
|
|
126
|
+
dp:s3 a dp:Slot ; dp:slotIndex 3 .
|
|
127
|
+
dp:s4 a dp:Slot ; dp:slotIndex 4 .
|
|
128
|
+
dp:s5 a dp:Slot ; dp:slotIndex 5 .
|
|
129
|
+
dp:s6 a dp:Slot ; dp:slotIndex 6 .
|
|
130
|
+
dp:s7 a dp:Slot ; dp:slotIndex 7 .
|
|
131
|
+
dp:s8 a dp:Slot ; dp:slotIndex 8 .
|
|
132
|
+
dp:s9 a dp:Slot ; dp:slotIndex 9 .
|
|
133
|
+
|
|
134
|
+
# ----------------------------------------------
|
|
135
|
+
# MealHandle mapping (stable URIs like dp:mP1_1)
|
|
136
|
+
# ----------------------------------------------
|
|
137
|
+
|
|
138
|
+
# P1
|
|
139
|
+
dp:hP1_1 a dp:MealHandle ; dp:philosopher dp:P1 ; dp:mealNo 1 ; dp:meal dp:mP1_1 .
|
|
140
|
+
dp:hP1_2 a dp:MealHandle ; dp:philosopher dp:P1 ; dp:mealNo 2 ; dp:meal dp:mP1_2 .
|
|
141
|
+
dp:hP1_3 a dp:MealHandle ; dp:philosopher dp:P1 ; dp:mealNo 3 ; dp:meal dp:mP1_3 .
|
|
142
|
+
|
|
143
|
+
# P2
|
|
144
|
+
dp:hP2_1 a dp:MealHandle ; dp:philosopher dp:P2 ; dp:mealNo 1 ; dp:meal dp:mP2_1 .
|
|
145
|
+
dp:hP2_2 a dp:MealHandle ; dp:philosopher dp:P2 ; dp:mealNo 2 ; dp:meal dp:mP2_2 .
|
|
146
|
+
dp:hP2_3 a dp:MealHandle ; dp:philosopher dp:P2 ; dp:mealNo 3 ; dp:meal dp:mP2_3 .
|
|
147
|
+
|
|
148
|
+
# P3
|
|
149
|
+
dp:hP3_1 a dp:MealHandle ; dp:philosopher dp:P3 ; dp:mealNo 1 ; dp:meal dp:mP3_1 .
|
|
150
|
+
dp:hP3_2 a dp:MealHandle ; dp:philosopher dp:P3 ; dp:mealNo 2 ; dp:meal dp:mP3_2 .
|
|
151
|
+
dp:hP3_3 a dp:MealHandle ; dp:philosopher dp:P3 ; dp:mealNo 3 ; dp:meal dp:mP3_3 .
|
|
152
|
+
|
|
153
|
+
# P4
|
|
154
|
+
dp:hP4_1 a dp:MealHandle ; dp:philosopher dp:P4 ; dp:mealNo 1 ; dp:meal dp:mP4_1 .
|
|
155
|
+
dp:hP4_2 a dp:MealHandle ; dp:philosopher dp:P4 ; dp:mealNo 2 ; dp:meal dp:mP4_2 .
|
|
156
|
+
dp:hP4_3 a dp:MealHandle ; dp:philosopher dp:P4 ; dp:mealNo 3 ; dp:meal dp:mP4_3 .
|
|
157
|
+
|
|
158
|
+
# P5
|
|
159
|
+
dp:hP5_1 a dp:MealHandle ; dp:philosopher dp:P5 ; dp:mealNo 1 ; dp:meal dp:mP5_1 .
|
|
160
|
+
dp:hP5_2 a dp:MealHandle ; dp:philosopher dp:P5 ; dp:mealNo 2 ; dp:meal dp:mP5_2 .
|
|
161
|
+
dp:hP5_3 a dp:MealHandle ; dp:philosopher dp:P5 ; dp:mealNo 3 ; dp:meal dp:mP5_3 .
|
|
162
|
+
|
|
163
|
+
# -------------------------------------------------------------------
|
|
164
|
+
# The 9-round hunger schedule (environment input)
|
|
165
|
+
#
|
|
166
|
+
# Start-of-round configs are: C0, C2, C4, C6, C8, C10, C12, C14, C16
|
|
167
|
+
# After-transfer configs are: C1, C3, C5, C7, C9, C11, C13, C15, C17
|
|
168
|
+
# End-of-round configs are: C2, C4, C6, C8, C10, C12, C14, C16, C18
|
|
169
|
+
# -------------------------------------------------------------------
|
|
170
|
+
|
|
171
|
+
dp:C0 a dp:Config ; dp:slot dp:s1 ; dp:cycle 1 ; dp:hungry dp:P1, dp:P3 ; dp:afterSends dp:C1 .
|
|
172
|
+
dp:C1 a dp:Config ; dp:afterEat dp:C2 .
|
|
173
|
+
dp:C2 a dp:Config ; dp:slot dp:s2 ; dp:cycle 1 ; dp:hungry dp:P2, dp:P4 ; dp:afterSends dp:C3 .
|
|
174
|
+
dp:C3 a dp:Config ; dp:afterEat dp:C4 .
|
|
175
|
+
dp:C4 a dp:Config ; dp:slot dp:s3 ; dp:cycle 1 ; dp:hungry dp:P5 ; dp:afterSends dp:C5 .
|
|
176
|
+
dp:C5 a dp:Config ; dp:afterEat dp:C6 .
|
|
177
|
+
dp:C6 a dp:Config ; dp:slot dp:s4 ; dp:cycle 2 ; dp:hungry dp:P1, dp:P3 ; dp:afterSends dp:C7 .
|
|
178
|
+
dp:C7 a dp:Config ; dp:afterEat dp:C8 .
|
|
179
|
+
dp:C8 a dp:Config ; dp:slot dp:s5 ; dp:cycle 2 ; dp:hungry dp:P2, dp:P4 ; dp:afterSends dp:C9 .
|
|
180
|
+
dp:C9 a dp:Config ; dp:afterEat dp:C10 .
|
|
181
|
+
dp:C10 a dp:Config ; dp:slot dp:s6 ; dp:cycle 2 ; dp:hungry dp:P5 ; dp:afterSends dp:C11 .
|
|
182
|
+
dp:C11 a dp:Config ; dp:afterEat dp:C12 .
|
|
183
|
+
dp:C12 a dp:Config ; dp:slot dp:s7 ; dp:cycle 3 ; dp:hungry dp:P1, dp:P3 ; dp:afterSends dp:C13 .
|
|
184
|
+
dp:C13 a dp:Config ; dp:afterEat dp:C14 .
|
|
185
|
+
dp:C14 a dp:Config ; dp:slot dp:s8 ; dp:cycle 3 ; dp:hungry dp:P2, dp:P4 ; dp:afterSends dp:C15 .
|
|
186
|
+
dp:C15 a dp:Config ; dp:afterEat dp:C16 .
|
|
187
|
+
dp:C16 a dp:Config ; dp:slot dp:s9 ; dp:cycle 3 ; dp:hungry dp:P5 ; dp:afterSends dp:C17 .
|
|
188
|
+
dp:C17 a dp:Config ; dp:afterEat dp:C18 .
|
|
189
|
+
dp:C18 a dp:Config .
|
|
190
|
+
|
|
191
|
+
# ---------------------------------------------------------------------
|
|
192
|
+
# Initial fork ownership (C0) — all forks Dirty
|
|
193
|
+
# Orientation breaks symmetry (one endpoint initially holds each fork).
|
|
194
|
+
# ---------------------------------------------------------------------
|
|
195
|
+
|
|
196
|
+
[ a dp:ForkState ; dp:in dp:C0 ; dp:fork dp:F12 ; dp:holder dp:P1 ; dp:cleanliness dp:Dirty ] .
|
|
197
|
+
[ a dp:ForkState ; dp:in dp:C0 ; dp:fork dp:F23 ; dp:holder dp:P2 ; dp:cleanliness dp:Dirty ] .
|
|
198
|
+
[ a dp:ForkState ; dp:in dp:C0 ; dp:fork dp:F34 ; dp:holder dp:P3 ; dp:cleanliness dp:Dirty ] .
|
|
199
|
+
[ a dp:ForkState ; dp:in dp:C0 ; dp:fork dp:F45 ; dp:holder dp:P4 ; dp:cleanliness dp:Dirty ] .
|
|
200
|
+
[ a dp:ForkState ; dp:in dp:C0 ; dp:fork dp:F51 ; dp:holder dp:P1 ; dp:cleanliness dp:Dirty ] .
|
|
201
|
+
|
|
202
|
+
# -------------------------------------------------------------------------------
|
|
203
|
+
# KeepFork facts (the "no transfer for this fork in this round" part)
|
|
204
|
+
# Only listed for forks that are NOT transferred; transfers are derived by rules.
|
|
205
|
+
# -------------------------------------------------------------------------------
|
|
206
|
+
|
|
207
|
+
# Round 1 (C0): only F23 transfers -> keep F12,F34,F45,F51
|
|
208
|
+
[ a dp:KeepFork ; dp:in dp:C0 ; dp:fork dp:F12 ] .
|
|
209
|
+
[ a dp:KeepFork ; dp:in dp:C0 ; dp:fork dp:F34 ] .
|
|
210
|
+
[ a dp:KeepFork ; dp:in dp:C0 ; dp:fork dp:F45 ] .
|
|
211
|
+
[ a dp:KeepFork ; dp:in dp:C0 ; dp:fork dp:F51 ] .
|
|
212
|
+
|
|
213
|
+
# Round 2 (C2): transfers F12,F23,F34 -> keep F45,F51
|
|
214
|
+
[ a dp:KeepFork ; dp:in dp:C2 ; dp:fork dp:F45 ] .
|
|
215
|
+
[ a dp:KeepFork ; dp:in dp:C2 ; dp:fork dp:F51 ] .
|
|
216
|
+
|
|
217
|
+
# Round 3 (C4): transfers F45,F51 -> keep F12,F23,F34
|
|
218
|
+
[ a dp:KeepFork ; dp:in dp:C4 ; dp:fork dp:F12 ] .
|
|
219
|
+
[ a dp:KeepFork ; dp:in dp:C4 ; dp:fork dp:F23 ] .
|
|
220
|
+
[ a dp:KeepFork ; dp:in dp:C4 ; dp:fork dp:F34 ] .
|
|
221
|
+
|
|
222
|
+
# Round 4 (C6): transfers F51,F12,F23,F34 -> keep F45
|
|
223
|
+
[ a dp:KeepFork ; dp:in dp:C6 ; dp:fork dp:F45 ] .
|
|
224
|
+
|
|
225
|
+
# Round 5 (C8): transfers F12,F23,F34,F45 -> keep F51
|
|
226
|
+
[ a dp:KeepFork ; dp:in dp:C8 ; dp:fork dp:F51 ] .
|
|
227
|
+
|
|
228
|
+
# Round 6 (C10): transfers F45,F51 -> keep F12,F23,F34
|
|
229
|
+
[ a dp:KeepFork ; dp:in dp:C10 ; dp:fork dp:F12 ] .
|
|
230
|
+
[ a dp:KeepFork ; dp:in dp:C10 ; dp:fork dp:F23 ] .
|
|
231
|
+
[ a dp:KeepFork ; dp:in dp:C10 ; dp:fork dp:F34 ] .
|
|
232
|
+
|
|
233
|
+
# Round 7 (C12): transfers F51,F12,F23,F34 -> keep F45
|
|
234
|
+
[ a dp:KeepFork ; dp:in dp:C12 ; dp:fork dp:F45 ] .
|
|
235
|
+
|
|
236
|
+
# Round 8 (C14): transfers F12,F23,F34,F45 -> keep F51
|
|
237
|
+
[ a dp:KeepFork ; dp:in dp:C14 ; dp:fork dp:F51 ] .
|
|
238
|
+
|
|
239
|
+
# Round 9 (C16): transfers F45,F51 -> keep F12,F23,F34
|
|
240
|
+
[ a dp:KeepFork ; dp:in dp:C16 ; dp:fork dp:F12 ] .
|
|
241
|
+
[ a dp:KeepFork ; dp:in dp:C16 ; dp:fork dp:F23 ] .
|
|
242
|
+
[ a dp:KeepFork ; dp:in dp:C16 ; dp:fork dp:F34 ] .
|
|
243
|
+
|
|
244
|
+
# ------------------
|
|
245
|
+
# Chandy–Misra rules
|
|
246
|
+
# ------------------
|
|
247
|
+
|
|
248
|
+
# R1: Hungry philosophers request any adjacent fork they do not hold.
|
|
249
|
+
# (We do left and right separately for clarity.)
|
|
250
|
+
|
|
251
|
+
{
|
|
252
|
+
?C a dp:Config .
|
|
253
|
+
?C dp:hungry ?P .
|
|
254
|
+
?P dp:leftFork ?F .
|
|
255
|
+
[ a dp:ForkState ; dp:in ?C ; dp:fork ?F ; dp:holder ?Q ] .
|
|
256
|
+
?Q log:notEqualTo ?P .
|
|
257
|
+
}
|
|
258
|
+
=>
|
|
259
|
+
{
|
|
260
|
+
[ a dp:Request ; dp:in ?C ; dp:from ?P ; dp:to ?Q ; dp:fork ?F ] .
|
|
261
|
+
} .
|
|
262
|
+
|
|
263
|
+
{
|
|
264
|
+
?C a dp:Config .
|
|
265
|
+
?C dp:hungry ?P .
|
|
266
|
+
?P dp:rightFork ?F .
|
|
267
|
+
[ a dp:ForkState ; dp:in ?C ; dp:fork ?F ; dp:holder ?Q ] .
|
|
268
|
+
?Q log:notEqualTo ?P .
|
|
269
|
+
}
|
|
270
|
+
=>
|
|
271
|
+
{
|
|
272
|
+
[ a dp:Request ; dp:in ?C ; dp:from ?P ; dp:to ?Q ; dp:fork ?F ] .
|
|
273
|
+
} .
|
|
274
|
+
|
|
275
|
+
# R2: Dirty-fork rule: if a fork is Dirty and requested, it is sent.
|
|
276
|
+
# (In the classic algorithm, the holder does not send while actually eating.
|
|
277
|
+
# This trace models sends happening in the "start-of-round" config, before meals.)
|
|
278
|
+
|
|
279
|
+
{
|
|
280
|
+
[ a dp:Request ; dp:in ?C ; dp:from ?P ; dp:to ?Q ; dp:fork ?F ] .
|
|
281
|
+
[ a dp:ForkState ; dp:in ?C ; dp:fork ?F ; dp:holder ?Q ; dp:cleanliness dp:Dirty ] .
|
|
282
|
+
}
|
|
283
|
+
=>
|
|
284
|
+
{
|
|
285
|
+
[ a dp:SendFork ; dp:in ?C ; dp:from ?Q ; dp:to ?P ; dp:fork ?F ] .
|
|
286
|
+
} .
|
|
287
|
+
|
|
288
|
+
# ----------------------------------------------
|
|
289
|
+
# State update: start-of-round -> after-transfer
|
|
290
|
+
# ----------------------------------------------
|
|
291
|
+
|
|
292
|
+
# U1: Apply transfers: after-transfer holder is the receiver; the fork becomes Clean.
|
|
293
|
+
{
|
|
294
|
+
?C dp:afterSends ?CS .
|
|
295
|
+
[ a dp:SendFork ; dp:in ?C ; dp:fork ?F ; dp:to ?P ] .
|
|
296
|
+
}
|
|
297
|
+
=>
|
|
298
|
+
{
|
|
299
|
+
[ a dp:ForkState ; dp:in ?CS ; dp:fork ?F ; dp:holder ?P ; dp:cleanliness dp:Clean ] .
|
|
300
|
+
} .
|
|
301
|
+
|
|
302
|
+
# U2: Apply keeps: if we declare KeepFork for a fork in a round, copy its state forward.
|
|
303
|
+
{
|
|
304
|
+
?C dp:afterSends ?CS .
|
|
305
|
+
[ a dp:KeepFork ; dp:in ?C ; dp:fork ?F ] .
|
|
306
|
+
[ a dp:ForkState ; dp:in ?C ; dp:fork ?F ; dp:holder ?H ; dp:cleanliness ?CL ] .
|
|
307
|
+
}
|
|
308
|
+
=>
|
|
309
|
+
{
|
|
310
|
+
[ a dp:ForkState ; dp:in ?CS ; dp:fork ?F ; dp:holder ?H ; dp:cleanliness ?CL ] .
|
|
311
|
+
} .
|
|
312
|
+
|
|
313
|
+
# ----------------------------------------------------------------------
|
|
314
|
+
# Meals: after-transfer, a hungry philosopher who holds both forks eats.
|
|
315
|
+
# ----------------------------------------------------------------------
|
|
316
|
+
|
|
317
|
+
{
|
|
318
|
+
?C dp:afterSends ?CS .
|
|
319
|
+
?C dp:slot ?S ; dp:cycle ?N .
|
|
320
|
+
?C dp:hungry ?P .
|
|
321
|
+
|
|
322
|
+
?H a dp:MealHandle ; dp:philosopher ?P ; dp:mealNo ?N ; dp:meal ?M .
|
|
323
|
+
|
|
324
|
+
?P dp:leftFork ?LF ; dp:rightFork ?RF .
|
|
325
|
+
|
|
326
|
+
[ a dp:ForkState ; dp:in ?CS ; dp:fork ?LF ; dp:holder ?P ] .
|
|
327
|
+
[ a dp:ForkState ; dp:in ?CS ; dp:fork ?RF ; dp:holder ?P ] .
|
|
328
|
+
}
|
|
329
|
+
=>
|
|
330
|
+
{
|
|
331
|
+
?M a dp:Meal ;
|
|
332
|
+
dp:philosopher ?P ;
|
|
333
|
+
dp:mealNo ?N ;
|
|
334
|
+
dp:inSlot ?S ;
|
|
335
|
+
dp:usesFork ?LF, ?RF .
|
|
336
|
+
} .
|
|
337
|
+
|
|
338
|
+
# ----------------------------------------------------------------------------
|
|
339
|
+
# State update: after-transfer -> end-of-round
|
|
340
|
+
#
|
|
341
|
+
# In this particular 9-round trace, every transferred fork is immediately used
|
|
342
|
+
# by an eater in that round, and kept forks were already Dirty.
|
|
343
|
+
# So at end-of-round, all forks are Dirty again.
|
|
344
|
+
# ----------------------------------------------------------------------------
|
|
345
|
+
|
|
346
|
+
# U3: End-of-round holders are the same as after-transfer holders.
|
|
347
|
+
# (Forks stay with whoever has them until requested in a later round.)
|
|
348
|
+
{
|
|
349
|
+
?CS dp:afterEat ?CE .
|
|
350
|
+
[ a dp:ForkState ; dp:in ?CS ; dp:fork ?F ; dp:holder ?H ] .
|
|
351
|
+
}
|
|
352
|
+
=>
|
|
353
|
+
{
|
|
354
|
+
[ a dp:ForkState ; dp:in ?CE ; dp:fork ?F ; dp:holder ?H ; dp:cleanliness dp:Dirty ] .
|
|
355
|
+
} .
|
|
356
|
+
|
|
357
|
+
# -------------------------------------------------
|
|
358
|
+
# Derived summaries: "each philosopher ate 3 times"
|
|
359
|
+
# -------------------------------------------------
|
|
360
|
+
|
|
361
|
+
{
|
|
362
|
+
?P a dp:Philosopher .
|
|
363
|
+
?M1 a dp:Meal ; dp:philosopher ?P ; dp:mealNo 1 .
|
|
364
|
+
?M2 a dp:Meal ; dp:philosopher ?P ; dp:mealNo 2 .
|
|
365
|
+
?M3 a dp:Meal ; dp:philosopher ?P ; dp:mealNo 3 .
|
|
366
|
+
}
|
|
367
|
+
=>
|
|
368
|
+
{
|
|
369
|
+
?P dp:ateTimes 3 .
|
|
370
|
+
} .
|
|
371
|
+
|
|
372
|
+
{
|
|
373
|
+
dp:P1 dp:ateTimes 3 .
|
|
374
|
+
dp:P2 dp:ateTimes 3 .
|
|
375
|
+
dp:P3 dp:ateTimes 3 .
|
|
376
|
+
dp:P4 dp:ateTimes 3 .
|
|
377
|
+
dp:P5 dp:ateTimes 3 .
|
|
378
|
+
}
|
|
379
|
+
=>
|
|
380
|
+
{
|
|
381
|
+
dp:Trace1 dp:everyoneAteTimes3 true .
|
|
382
|
+
} .
|
|
383
|
+
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
VERSION "1.2"
|
|
2
|
+
|
|
2
3
|
PREFIX : <http://www.example.org/>
|
|
3
4
|
PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
|
|
4
5
|
|
|
5
|
-
|
|
6
|
+
_:e38 :familyName "Smith" .
|
|
6
7
|
_:anno rdf:reifies <<( _:e38 :jobTitle "Designer" )>> .
|
|
7
|
-
|
|
8
|
+
_:anno :accordingTo _:e22 .
|
|
@@ -0,0 +1,205 @@
|
|
|
1
|
+
# =========================================================================
|
|
2
|
+
# Kaprekar’s routine for 4-digit numbers
|
|
3
|
+
#
|
|
4
|
+
# What it does
|
|
5
|
+
# Enumerates all 4-digit numbers 0000..9999 (leading zeros allowed),
|
|
6
|
+
# applies the Kaprekar step:
|
|
7
|
+
# - take the 4 digits of n
|
|
8
|
+
# - sort digits descending to form D, ascending to form A
|
|
9
|
+
# - next = D − A
|
|
10
|
+
# and emits triples of the form:
|
|
11
|
+
# 3524 :kaprekar (3087 8352 6174) .
|
|
12
|
+
#
|
|
13
|
+
# Output convention
|
|
14
|
+
# The list contains the successive results starting from the *first* step
|
|
15
|
+
# and ends at 6174 (Kaprekar’s constant).
|
|
16
|
+
#
|
|
17
|
+
# Skipping the repdigit → 0000 basin
|
|
18
|
+
# Starts that eventually reach 0000 (e.g., 1111, 2222, … and anything
|
|
19
|
+
# that falls into that basin) can be omitted by adding constraints that
|
|
20
|
+
# require the chain to end in 6174.
|
|
21
|
+
#
|
|
22
|
+
# Performance notes
|
|
23
|
+
# - The step computation can be sped up by using the identity:
|
|
24
|
+
# next = 999*(a3-a0) + 90*(a2-a1)
|
|
25
|
+
# where a0<=a1<=a2<=a3 are the digits sorted ascending.
|
|
26
|
+
# This avoids explicitly constructing D and A as 4-digit numbers.
|
|
27
|
+
# - For 4-digit Kaprekar, the maximum number of steps to reach 6174 is 7,
|
|
28
|
+
# so the path rules can be unrolled to a fixed bound (no recursion),
|
|
29
|
+
# which improves termination and speed.
|
|
30
|
+
#
|
|
31
|
+
# Predicates used (typical)
|
|
32
|
+
# :kaprekar — final output predicate: start -> (sequence ... 6174)
|
|
33
|
+
# kap:step — internal: n -> next for one Kaprekar step
|
|
34
|
+
# =========================================================================
|
|
35
|
+
|
|
36
|
+
@prefix : <http://example.org/#>.
|
|
37
|
+
@prefix kap: <http://example.org/kaprekar#>.
|
|
38
|
+
@prefix math: <http://www.w3.org/2000/10/swap/math#>.
|
|
39
|
+
@prefix list: <http://www.w3.org/2000/10/swap/list#>.
|
|
40
|
+
@prefix log: <http://www.w3.org/2000/10/swap/log#>.
|
|
41
|
+
|
|
42
|
+
# Define the digit list ONCE (avoid repeating a list literal 4 times)
|
|
43
|
+
:digitList :items (0 1 2 3 4 5 6 7 8 9).
|
|
44
|
+
|
|
45
|
+
# Output: only :kaprekar triples
|
|
46
|
+
{ ?n :kaprekar ?seq. } log:query { ?n :kaprekar ?seq. }.
|
|
47
|
+
|
|
48
|
+
# -------------------------------------------------------
|
|
49
|
+
# Precompute kap:step for all 0000..9999.
|
|
50
|
+
# Uses identity: if sorted digits are a0<=a1<=a2<=a3 then
|
|
51
|
+
# desc-asc = 999*(a3-a0) + 90*(a2-a1)
|
|
52
|
+
# -------------------------------------------------------
|
|
53
|
+
|
|
54
|
+
{
|
|
55
|
+
:digitList :items ?L.
|
|
56
|
+
|
|
57
|
+
?L list:member ?d1.
|
|
58
|
+
?L list:member ?d2.
|
|
59
|
+
?L list:member ?d3.
|
|
60
|
+
?L list:member ?d4.
|
|
61
|
+
|
|
62
|
+
# build n = 1000*d1 + 100*d2 + 10*d3 + d4
|
|
63
|
+
(?d1 1000) math:product ?p1.
|
|
64
|
+
(?d2 100) math:product ?p2.
|
|
65
|
+
(?d3 10) math:product ?p3.
|
|
66
|
+
(?d4 1) math:product ?p4.
|
|
67
|
+
(?p1 ?p2 ?p3 ?p4) math:sum ?n.
|
|
68
|
+
|
|
69
|
+
# sort digits once
|
|
70
|
+
(?d1 ?d2 ?d3 ?d4) list:sort ?asc.
|
|
71
|
+
|
|
72
|
+
# unpack a0 a1 a2 a3
|
|
73
|
+
?asc list:firstRest (?a0 ?r0).
|
|
74
|
+
?r0 list:firstRest (?a1 ?r1).
|
|
75
|
+
?r1 list:firstRest (?a2 ?r2).
|
|
76
|
+
?r2 list:firstRest (?a3 ()).
|
|
77
|
+
|
|
78
|
+
# next = 999*(a3-a0) + 90*(a2-a1)
|
|
79
|
+
(?a3 ?a0) math:difference ?x.
|
|
80
|
+
(?a2 ?a1) math:difference ?y.
|
|
81
|
+
(?x 999) math:product ?px.
|
|
82
|
+
(?y 90) math:product ?py.
|
|
83
|
+
(?px ?py) math:sum ?next.
|
|
84
|
+
} => {
|
|
85
|
+
?n kap:step ?next.
|
|
86
|
+
}.
|
|
87
|
+
|
|
88
|
+
# ------------------------------------------------------------------
|
|
89
|
+
# Emit only chains that end in 6174 (skip the repdigit->0 basin)
|
|
90
|
+
# Maximum steps to 6174 is 7, so we unroll 1..7.
|
|
91
|
+
#
|
|
92
|
+
# Convention: output list includes each intermediate INCLUDING 6174.
|
|
93
|
+
# Example: 3524 -> (3087 8352 6174)
|
|
94
|
+
# ------------------------------------------------------------------
|
|
95
|
+
|
|
96
|
+
# n = 6174 itself (optional; keep if you want it in output)
|
|
97
|
+
6174 :kaprekar (6174).
|
|
98
|
+
|
|
99
|
+
# 1 step
|
|
100
|
+
{
|
|
101
|
+
?n log:notEqualTo 6174.
|
|
102
|
+
?n kap:step 6174.
|
|
103
|
+
# exclude repdigits/0 basin:
|
|
104
|
+
?n log:notEqualTo 0.
|
|
105
|
+
} => {
|
|
106
|
+
?n :kaprekar (6174).
|
|
107
|
+
}.
|
|
108
|
+
|
|
109
|
+
# 2 steps
|
|
110
|
+
{
|
|
111
|
+
?n log:notEqualTo 6174.
|
|
112
|
+
?n log:notEqualTo 0.
|
|
113
|
+
?n kap:step ?s1.
|
|
114
|
+
?s1 log:notEqualTo 0.
|
|
115
|
+
?s1 log:notEqualTo 6174.
|
|
116
|
+
?s1 kap:step 6174.
|
|
117
|
+
} => {
|
|
118
|
+
?n :kaprekar (?s1 6174).
|
|
119
|
+
}.
|
|
120
|
+
|
|
121
|
+
# 3 steps
|
|
122
|
+
{
|
|
123
|
+
?n log:notEqualTo 6174.
|
|
124
|
+
?n log:notEqualTo 0.
|
|
125
|
+
?n kap:step ?s1.
|
|
126
|
+
?s1 log:notEqualTo 0. ?s1 log:notEqualTo 6174.
|
|
127
|
+
?s1 kap:step ?s2.
|
|
128
|
+
?s2 log:notEqualTo 0. ?s2 log:notEqualTo 6174.
|
|
129
|
+
?s2 kap:step 6174.
|
|
130
|
+
} => {
|
|
131
|
+
?n :kaprekar (?s1 ?s2 6174).
|
|
132
|
+
}.
|
|
133
|
+
|
|
134
|
+
# 4 steps
|
|
135
|
+
{
|
|
136
|
+
?n log:notEqualTo 6174.
|
|
137
|
+
?n log:notEqualTo 0.
|
|
138
|
+
?n kap:step ?s1.
|
|
139
|
+
?s1 log:notEqualTo 0. ?s1 log:notEqualTo 6174.
|
|
140
|
+
?s1 kap:step ?s2.
|
|
141
|
+
?s2 log:notEqualTo 0. ?s2 log:notEqualTo 6174.
|
|
142
|
+
?s2 kap:step ?s3.
|
|
143
|
+
?s3 log:notEqualTo 0. ?s3 log:notEqualTo 6174.
|
|
144
|
+
?s3 kap:step 6174.
|
|
145
|
+
} => {
|
|
146
|
+
?n :kaprekar (?s1 ?s2 ?s3 6174).
|
|
147
|
+
}.
|
|
148
|
+
|
|
149
|
+
# 5 steps
|
|
150
|
+
{
|
|
151
|
+
?n log:notEqualTo 6174.
|
|
152
|
+
?n log:notEqualTo 0.
|
|
153
|
+
?n kap:step ?s1.
|
|
154
|
+
?s1 log:notEqualTo 0. ?s1 log:notEqualTo 6174.
|
|
155
|
+
?s1 kap:step ?s2.
|
|
156
|
+
?s2 log:notEqualTo 0. ?s2 log:notEqualTo 6174.
|
|
157
|
+
?s2 kap:step ?s3.
|
|
158
|
+
?s3 log:notEqualTo 0. ?s3 log:notEqualTo 6174.
|
|
159
|
+
?s3 kap:step ?s4.
|
|
160
|
+
?s4 log:notEqualTo 0. ?s4 log:notEqualTo 6174.
|
|
161
|
+
?s4 kap:step 6174.
|
|
162
|
+
} => {
|
|
163
|
+
?n :kaprekar (?s1 ?s2 ?s3 ?s4 6174).
|
|
164
|
+
}.
|
|
165
|
+
|
|
166
|
+
# 6 steps
|
|
167
|
+
{
|
|
168
|
+
?n log:notEqualTo 6174.
|
|
169
|
+
?n log:notEqualTo 0.
|
|
170
|
+
?n kap:step ?s1.
|
|
171
|
+
?s1 log:notEqualTo 0. ?s1 log:notEqualTo 6174.
|
|
172
|
+
?s1 kap:step ?s2.
|
|
173
|
+
?s2 log:notEqualTo 0. ?s2 log:notEqualTo 6174.
|
|
174
|
+
?s2 kap:step ?s3.
|
|
175
|
+
?s3 log:notEqualTo 0. ?s3 log:notEqualTo 6174.
|
|
176
|
+
?s3 kap:step ?s4.
|
|
177
|
+
?s4 log:notEqualTo 0. ?s4 log:notEqualTo 6174.
|
|
178
|
+
?s4 kap:step ?s5.
|
|
179
|
+
?s5 log:notEqualTo 0. ?s5 log:notEqualTo 6174.
|
|
180
|
+
?s5 kap:step 6174.
|
|
181
|
+
} => {
|
|
182
|
+
?n :kaprekar (?s1 ?s2 ?s3 ?s4 ?s5 6174).
|
|
183
|
+
}.
|
|
184
|
+
|
|
185
|
+
# 7 steps (max)
|
|
186
|
+
{
|
|
187
|
+
?n log:notEqualTo 6174.
|
|
188
|
+
?n log:notEqualTo 0.
|
|
189
|
+
?n kap:step ?s1.
|
|
190
|
+
?s1 log:notEqualTo 0. ?s1 log:notEqualTo 6174.
|
|
191
|
+
?s1 kap:step ?s2.
|
|
192
|
+
?s2 log:notEqualTo 0. ?s2 log:notEqualTo 6174.
|
|
193
|
+
?s2 kap:step ?s3.
|
|
194
|
+
?s3 log:notEqualTo 0. ?s3 log:notEqualTo 6174.
|
|
195
|
+
?s3 kap:step ?s4.
|
|
196
|
+
?s4 log:notEqualTo 0. ?s4 log:notEqualTo 6174.
|
|
197
|
+
?s4 kap:step ?s5.
|
|
198
|
+
?s5 log:notEqualTo 0. ?s5 log:notEqualTo 6174.
|
|
199
|
+
?s5 kap:step ?s6.
|
|
200
|
+
?s6 log:notEqualTo 0. ?s6 log:notEqualTo 6174.
|
|
201
|
+
?s6 kap:step 6174.
|
|
202
|
+
} => {
|
|
203
|
+
?n :kaprekar (?s1 ?s2 ?s3 ?s4 ?s5 ?s6 6174).
|
|
204
|
+
}.
|
|
205
|
+
|