eyeling 1.17.2 → 1.18.0

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.
@@ -0,0 +1,227 @@
1
+ # ===========================================================================
2
+ # pn-junction-tunneling.n3
3
+ #
4
+ # - ordinary depletion width = 8 nm
5
+ # - tunnel depletion width = 1 nm
6
+ # - filled N-side states = [1, 2, 3, 4]
7
+ # - empty P-side states @ 0V = [3, 4, 5, 6]
8
+ # - bias points = 0..6
9
+ #
10
+ # For each bias, the empty P-side levels shift downward by the bias amount.
11
+ # A shifted level contributes 1 to the current proxy exactly when it lands in
12
+ # the occupied N-side window [1, 4]. The four slot contributions are summed.
13
+ # ===========================================================================
14
+
15
+ @prefix : <http://example.org/pn-junction-tunneling#> .
16
+ @prefix log: <http://www.w3.org/2000/10/swap/log#> .
17
+ @prefix math: <http://www.w3.org/2000/10/swap/math#> .
18
+ @prefix list: <http://www.w3.org/2000/10/swap/list#> .
19
+ @prefix string: <http://www.w3.org/2000/10/swap/string#> .
20
+
21
+ # -----
22
+ # Facts
23
+ # -----
24
+
25
+ :case :name "pn-junction-tunneling" .
26
+ :case :ordinaryDepletionWidthNm 8 .
27
+ :case :tunnelDepletionWidthNm 1 .
28
+ :case :nFilledLevels (1 2 3 4) .
29
+ :case :pEmptyZeroBiasLevels (3 4 5 6) .
30
+
31
+ :b0 :value 0 .
32
+ :b1 :value 1 .
33
+ :b2 :value 2 .
34
+ :b3 :value 3 .
35
+ :b4 :value 4 .
36
+ :b5 :value 5 .
37
+ :b6 :value 6 .
38
+
39
+ # -----
40
+ # Logic
41
+ # -----
42
+
43
+ # Heavy doping is modeled as a much narrower depletion region.
44
+ { :case :tunnelDepletionWidthNm ?t .
45
+ :case :ordinaryDepletionWidthNm ?o .
46
+ ?t math:lessThan ?o .
47
+ }
48
+ => { :case :barrierIsNarrower true . } .
49
+
50
+ # For each bias node and each zero-bias P-side slot, shift the level downward:
51
+ # shifted = zeroBiasLevel - bias.
52
+ { ?bnode list:in (:b0 :b1 :b2 :b3 :b4 :b5 :b6) .
53
+ ?bnode :value ?bias .
54
+ :case :pEmptyZeroBiasLevels ?levels .
55
+ ?levels list:iterate ( ?slot ?zeroLevel ) .
56
+ ( ?zeroLevel ?bias ) math:difference ?shifted .
57
+ }
58
+ => { ( ?bnode ?slot ) :shiftedLevel ?shifted . } .
59
+
60
+ # Each shifted slot contributes 1 when it falls inside the occupied N-side
61
+ # window [1, 4], otherwise 0.
62
+ { ( ?bnode ?slot ) :shiftedLevel ?shifted .
63
+ ?shifted math:notLessThan 1 .
64
+ ?shifted math:notGreaterThan 4 .
65
+ }
66
+ => { ( ?bnode ?slot ) :overlapValue 1 . } .
67
+
68
+ { ( ?bnode ?slot ) :shiftedLevel ?shifted .
69
+ ?shifted math:lessThan 1 .
70
+ }
71
+ => { ( ?bnode ?slot ) :overlapValue 0 . } .
72
+
73
+ { ( ?bnode ?slot ) :shiftedLevel ?shifted .
74
+ ?shifted math:greaterThan 4 .
75
+ }
76
+ => { ( ?bnode ?slot ) :overlapValue 0 . } .
77
+
78
+ # The current proxy is the sum of the four slot contributions.
79
+ { ( ?bnode 0 ) :overlapValue ?v0 .
80
+ ( ?bnode 1 ) :overlapValue ?v1 .
81
+ ( ?bnode 2 ) :overlapValue ?v2 .
82
+ ( ?bnode 3 ) :overlapValue ?v3 .
83
+ ( ?v0 ?v1 ?v2 ?v3 ) math:sum ?current .
84
+ }
85
+ => { ?bnode :currentProxy ?current . } .
86
+
87
+ # Peak = the unique maximum at bias 2 in this toy curve.
88
+ { :b2 :currentProxy ?peak .
89
+ :b0 :currentProxy ?c0 . ?peak math:greaterThan ?c0 .
90
+ :b1 :currentProxy ?c1 . ?peak math:greaterThan ?c1 .
91
+ :b3 :currentProxy ?c3 . ?peak math:greaterThan ?c3 .
92
+ :b4 :currentProxy ?c4 . ?peak math:greaterThan ?c4 .
93
+ :b5 :currentProxy ?c5 . ?peak math:greaterThan ?c5 .
94
+ :b6 :currentProxy ?c6 . ?peak math:greaterThan ?c6 .
95
+ }
96
+ => { :case :peakBias 2 .
97
+ :case :peakCurrent ?peak . } .
98
+
99
+ # High-bias valley = the final sampled point, matching the Rust code.
100
+ { :b6 :currentProxy ?valley . }
101
+ => { :case :valleyBias 6 .
102
+ :case :valleyCurrent ?valley . } .
103
+
104
+ # A negative differential region is present once the curve drops after the peak.
105
+ { :b2 :currentProxy ?c2 .
106
+ :b3 :currentProxy ?c3 .
107
+ ?c2 math:greaterThan ?c3 .
108
+ }
109
+ => { :case :negativeDifferentialRegion true . } .
110
+
111
+ { :case :peakBias ?peakBias .
112
+ :case :valleyBias ?valleyBias .
113
+ ?peakBias math:lessThan ?valleyBias .
114
+ }
115
+ => { :case :peakIsBeforeValley true . } .
116
+
117
+ { :case :valleyCurrent 0 . }
118
+ => { :case :overlapClosesAtHighBias true . } .
119
+
120
+ { :case :peakCurrent ?peakCurrent .
121
+ :case :nFilledLevels ?nLevels .
122
+ ?nLevels list:length ?nCount .
123
+ ?peakCurrent math:equalTo ?nCount .
124
+ }
125
+ => { :case :peakMatchesFullOverlap true . } .
126
+
127
+ # -----------------------------------------------
128
+ # Presentation (ARC: Answer • Reason Why • Check)
129
+ # -----------------------------------------------
130
+
131
+ # Answer
132
+ { :case :peakBias ?peakBias .
133
+ :case :peakCurrent ?peakCurrent .
134
+ :case :negativeDifferentialRegion true .
135
+ ( "peak bias : %s\n" ?peakBias ) string:format ?peakBiasLine .
136
+ ( "peak current proxy : %s\n" ?peakCurrent ) string:format ?peakCurrentLine .
137
+ }
138
+ => {
139
+ :01-answer-1 log:outputString "=== Answer ===\n" .
140
+ :01-answer-2 log:outputString "In this toy PN-junction tunneling model, heavy doping narrows the depletion region enough for a tunneling window that rises to a peak and then falls, producing a negative-differential region.\n" .
141
+ :01-answer-3 log:outputString "case : pn-junction-tunneling\n" .
142
+ :01-answer-4 log:outputString ?peakBiasLine .
143
+ :01-answer-5 log:outputString ?peakCurrentLine .
144
+ :01-answer-6 log:outputString "negative differential region : yes\n\n" .
145
+ } .
146
+
147
+ # Reason Why
148
+ { :case :ordinaryDepletionWidthNm ?ordinary .
149
+ :case :tunnelDepletionWidthNm ?tunnel .
150
+ :b0 :currentProxy ?c0 .
151
+ :b1 :currentProxy ?c1 .
152
+ :b2 :currentProxy ?c2 .
153
+ :b3 :currentProxy ?c3 .
154
+ :b4 :currentProxy ?c4 .
155
+ :b5 :currentProxy ?c5 .
156
+ :b6 :currentProxy ?c6 .
157
+ :case :peakBias ?peakBias .
158
+ :case :peakCurrent ?peakCurrent .
159
+ :case :valleyBias ?valleyBias .
160
+ :case :valleyCurrent ?valleyCurrent .
161
+ ( "%s->%s, %s->%s, %s->%s, %s->%s, %s->%s, %s->%s, %s->%s"
162
+ 0 ?c0 1 ?c1 2 ?c2 3 ?c3 4 ?c4 5 ?c5 6 ?c6 ) string:format ?curve .
163
+ ( "ordinary depletion width (nm) : %s\n" ?ordinary ) string:format ?ordinaryLine .
164
+ ( "tunnel depletion width (nm) : %s\n" ?tunnel ) string:format ?tunnelLine .
165
+ ( "bias -> overlap current proxy : %s\n" ?curve ) string:format ?curveLine .
166
+ ( "peak point : %s -> %s\n" ?peakBias ?peakCurrent ) string:format ?peakLine .
167
+ ( "high-bias point : %s -> %s\n" ?valleyBias ?valleyCurrent ) string:format ?valleyLine .
168
+ }
169
+ => {
170
+ :02-why-1 log:outputString "=== Reason Why ===\n" .
171
+ :02-why-2 log:outputString "We model tunneling current as an exact overlap count between filled N-side states and empty P-side states while forward bias shifts the bands. Heavy doping is represented by a much narrower depletion region.\n" .
172
+ :02-why-3 log:outputString ?ordinaryLine .
173
+ :02-why-4 log:outputString ?tunnelLine .
174
+ :02-why-5 log:outputString "filled N-side states : [1, 2, 3, 4]\n" .
175
+ :02-why-6 log:outputString "empty P-side states at 0 bias : [3, 4, 5, 6]\n" .
176
+ :02-why-7 log:outputString ?curveLine .
177
+ :02-why-8 log:outputString ?peakLine .
178
+ :02-why-9 log:outputString ?valleyLine .
179
+ :02-why-99 log:outputString "\n" .
180
+ } .
181
+
182
+ # Check
183
+ { :case :barrierIsNarrower true .
184
+ :case :peakIsBeforeValley true .
185
+ :case :negativeDifferentialRegion true .
186
+ :case :overlapClosesAtHighBias true .
187
+ :case :peakMatchesFullOverlap true .
188
+ }
189
+ => {
190
+ :03-check-1 log:outputString "=== Check ===\n" .
191
+ :03-check-2 log:outputString "heavily doped barrier is narrower : yes\n" .
192
+ :03-check-3 log:outputString "peak occurs before overlap closes : yes\n" .
193
+ :03-check-4 log:outputString "negative differential region present : yes\n" .
194
+ :03-check-5 log:outputString "high-bias overlap closes : yes\n" .
195
+ :03-check-6 log:outputString "peak equals full four-state overlap: yes\n" .
196
+ } .
197
+
198
+ # ------------------
199
+ # Verification fuses
200
+ # ------------------
201
+
202
+ # If any of the key invariants fail, stop the run loudly.
203
+
204
+ { :case :tunnelDepletionWidthNm ?t .
205
+ :case :ordinaryDepletionWidthNm ?o .
206
+ ?t math:notLessThan ?o .
207
+ } => false .
208
+
209
+ { :case :peakBias ?peakBias .
210
+ :case :valleyBias ?valleyBias .
211
+ ?peakBias math:notLessThan ?valleyBias .
212
+ } => false .
213
+
214
+ { :b2 :currentProxy ?c2 .
215
+ :b3 :currentProxy ?c3 .
216
+ ?c2 math:notGreaterThan ?c3 .
217
+ } => false .
218
+
219
+ { :case :valleyCurrent ?valleyCurrent .
220
+ ?valleyCurrent math:notEqualTo 0 .
221
+ } => false .
222
+
223
+ { :case :peakCurrent ?peakCurrent .
224
+ :case :nFilledLevels ?nLevels .
225
+ ?nLevels list:length ?nCount .
226
+ ?peakCurrent math:notEqualTo ?nCount .
227
+ } => false .
@@ -0,0 +1,257 @@
1
+ # ==================================================
2
+ # sudoku.n3
3
+ #
4
+ # A standalone Sudoku solver and report generator.
5
+ #
6
+ # Edit :case :puzzle to solve another puzzle.
7
+ # Accepted blanks: 0, ., _
8
+ # Whitespace and ASCII board separators are ignored.
9
+ # ==================================================
10
+
11
+ @prefix : <http://example.org/sudoku#> .
12
+ @prefix log: <http://www.w3.org/2000/10/swap/log#> .
13
+ @prefix string: <http://www.w3.org/2000/10/swap/string#> .
14
+ @prefix sb: <http://example.org/sudoku-builtin#> .
15
+
16
+ # -----
17
+ # Facts
18
+ # -----
19
+
20
+ :case :name "sudoku" .
21
+ :case :puzzleName "classic" .
22
+ :case :puzzle "100007090030020008009600500005300900010080002600004000300000010040000007007000300" .
23
+
24
+ # ------------------------------------
25
+ # Report facts from the solver builtin
26
+ # ------------------------------------
27
+
28
+ { :case :puzzle ?p .
29
+ ?p sb:status ?status .
30
+ ?p sb:normalizedPuzzle ?normalized .
31
+ ?p sb:givens ?givens .
32
+ ?p sb:blanks ?blanks .
33
+ ?p sb:puzzleText ?puzzleText .
34
+ }
35
+ => {
36
+ :case :status ?status ;
37
+ :normalizedPuzzle ?normalized ;
38
+ :givens ?givens ;
39
+ :blanks ?blanks ;
40
+ :puzzleText ?puzzleText .
41
+ } .
42
+
43
+ { :case :puzzle ?p .
44
+ ?p sb:status "ok" .
45
+ ?p sb:solution ?solution ;
46
+ sb:solutionText ?solutionText ;
47
+ sb:forcedMoves ?forced ;
48
+ sb:guessedMoves ?guessed ;
49
+ sb:recursiveNodes ?nodes ;
50
+ sb:backtracks ?backtracks ;
51
+ sb:maxDepth ?maxDepth ;
52
+ sb:unique ?unique ;
53
+ sb:moveSummary ?moveSummary ;
54
+ sb:givensPreservedText ?givensPreserved ;
55
+ sb:noBlanksText ?noBlanks ;
56
+ sb:rowsCompleteText ?rowsComplete ;
57
+ sb:colsCompleteText ?colsComplete ;
58
+ sb:boxesCompleteText ?boxesComplete ;
59
+ sb:replayLegalText ?replayLegal ;
60
+ sb:storyConsistentText ?storyConsistent .
61
+ }
62
+ => {
63
+ :case :solution ?solution ;
64
+ :solutionText ?solutionText ;
65
+ :forcedMoves ?forced ;
66
+ :guessedMoves ?guessed ;
67
+ :recursiveNodes ?nodes ;
68
+ :backtracks ?backtracks ;
69
+ :maxDepth ?maxDepth ;
70
+ :unique ?unique ;
71
+ :moveSummary ?moveSummary ;
72
+ :givensPreserved ?givensPreserved ;
73
+ :noBlanks ?noBlanks ;
74
+ :rowsComplete ?rowsComplete ;
75
+ :colsComplete ?colsComplete ;
76
+ :boxesComplete ?boxesComplete ;
77
+ :replayLegal ?replayLegal ;
78
+ :storyConsistent ?storyConsistent .
79
+ } .
80
+
81
+ { :case :puzzle ?p .
82
+ ?p sb:status ?status .
83
+ ?status string:notEqualIgnoringCase "ok" .
84
+ ?p sb:error ?error .
85
+ }
86
+ => { :case :error ?error . } .
87
+
88
+ # ------------
89
+ # Presentation
90
+ # ------------
91
+
92
+ # Successful solve, unique.
93
+ { :case :status "ok" .
94
+ :case :unique true .
95
+ :case :givens ?givens ;
96
+ :blanks ?blanks ;
97
+ :forcedMoves ?forced ;
98
+ :guessedMoves ?guessed ;
99
+ :recursiveNodes ?nodes ;
100
+ :backtracks ?backtracks ;
101
+ :moveSummary ?moveSummary ;
102
+ :puzzleText ?puzzleText ;
103
+ :solutionText ?solutionText .
104
+ ( "The puzzle is solved, and the completed grid is the unique valid Sudoku solution.\n" ) string:concatenation ?answerText .
105
+ ( "The solver starts from %s clues and fills the remaining %s cells by combining constraint propagation with depth-first search. At each step it chooses the empty cell with the fewest legal digits, places forced singles immediately, and only guesses when more than one candidate remains. Across the search it made %s forced placements and tried %s guesses, visited %s search nodes overall, and backtracked %s times before reaching the completed grid. The solver also confirmed that the solution is unique. Early steps: %s"
106
+ ?givens ?blanks ?forced ?guessed ?nodes ?backtracks ?moveSummary ) string:format ?reasonText .
107
+ }
108
+ => {
109
+ :01-answer log:outputString "=== Answer ===\n" ;
110
+ log:outputString ?answerText .
111
+ :01a-answer log:outputString "case : sudoku\n" ;
112
+ log:outputString "default puzzle : classic\n\n" ;
113
+ log:outputString "Puzzle\n" ;
114
+ log:outputString ?puzzleText ;
115
+ log:outputString "\n" ;
116
+ log:outputString "Completed grid\n" ;
117
+ log:outputString ?solutionText ;
118
+ log:outputString "\n" .
119
+ :02-reason log:outputString "=== Reason Why ===\n" ;
120
+ log:outputString ?reasonText ;
121
+ log:outputString "\n\n" .
122
+ } .
123
+
124
+ # Successful solve, not unique.
125
+ { :case :status "ok" .
126
+ :case :unique false .
127
+ :case :givens ?givens ;
128
+ :blanks ?blanks ;
129
+ :forcedMoves ?forced ;
130
+ :guessedMoves ?guessed ;
131
+ :recursiveNodes ?nodes ;
132
+ :backtracks ?backtracks ;
133
+ :moveSummary ?moveSummary ;
134
+ :puzzleText ?puzzleText ;
135
+ :solutionText ?solutionText .
136
+ ( "The puzzle is solved, and the completed grid is a valid Sudoku solution.\n" ) string:concatenation ?answerText .
137
+ ( "The solver starts from %s clues and fills the remaining %s cells by combining constraint propagation with depth-first search. At each step it chooses the empty cell with the fewest legal digits, places forced singles immediately, and only guesses when more than one candidate remains. Across the search it made %s forced placements and tried %s guesses, visited %s search nodes overall, and backtracked %s times before reaching the completed grid. The solver found a valid solution, but there is more than one. Early steps: %s"
138
+ ?givens ?blanks ?forced ?guessed ?nodes ?backtracks ?moveSummary ) string:format ?reasonText .
139
+ }
140
+ => {
141
+ :01-answer log:outputString "=== Answer ===\n" ;
142
+ log:outputString ?answerText .
143
+ :01a-answer log:outputString "case : sudoku\n" ;
144
+ log:outputString "default puzzle : classic\n\n" ;
145
+ log:outputString "Puzzle\n" ;
146
+ log:outputString ?puzzleText ;
147
+ log:outputString "\n" ;
148
+ log:outputString "Completed grid\n" ;
149
+ log:outputString ?solutionText ;
150
+ log:outputString "\n" .
151
+ :02-reason log:outputString "=== Reason Why ===\n" ;
152
+ log:outputString ?reasonText ;
153
+ log:outputString "\n\n" .
154
+ } .
155
+
156
+ # Invalid input length / characters.
157
+ { :case :status "invalid-input" .
158
+ :case :error ?error .
159
+ }
160
+ => {
161
+ :01-answer log:outputString "=== Answer ===\n" ;
162
+ log:outputString "The supplied puzzle is not well formed and cannot be parsed as a 9×9 Sudoku.\n" ;
163
+ log:outputString "case : sudoku\n\n" .
164
+ :02-reason log:outputString "=== Reason Why ===\n" ;
165
+ log:outputString ?error ;
166
+ log:outputString "\n\n" .
167
+ } .
168
+
169
+ # Illegal clues.
170
+ { :case :status "illegal-clues" .
171
+ :case :puzzleText ?puzzleText ;
172
+ :error ?error .
173
+ }
174
+ => {
175
+ :01-answer log:outputString "=== Answer ===\n" ;
176
+ log:outputString "The puzzle is invalid and cannot be solved as a standard Sudoku.\n" ;
177
+ log:outputString "case : sudoku\n\n" ;
178
+ log:outputString "Puzzle\n" ;
179
+ log:outputString ?puzzleText ;
180
+ log:outputString "\n" .
181
+ :02-reason log:outputString "=== Reason Why ===\n" ;
182
+ log:outputString ?error ;
183
+ log:outputString "\n\n" .
184
+ } .
185
+
186
+ # Unsatisfiable puzzle.
187
+ { :case :status "unsatisfiable" .
188
+ :case :givens ?givens ;
189
+ :blanks ?blanks ;
190
+ :recursiveNodes ?nodes ;
191
+ :backtracks ?backtracks ;
192
+ :puzzleText ?puzzleText .
193
+ ( "The solver explored %s search nodes with minimum-remaining-values branching and backtracked %s times, but every branch eventually contradicted the row, column, or box constraints."
194
+ ?nodes ?backtracks ) string:format ?reasonText .
195
+ }
196
+ => {
197
+ :01-answer log:outputString "=== Answer ===\n" ;
198
+ log:outputString "No valid Sudoku solution exists for the supplied puzzle.\n" ;
199
+ log:outputString "case : sudoku\n" ;
200
+ log:outputString "default puzzle : classic\n" ;
201
+ log:outputString "\nPuzzle\n" ;
202
+ log:outputString ?puzzleText ;
203
+ log:outputString "\n" .
204
+ :02-reason log:outputString "=== Reason Why ===\n" ;
205
+ log:outputString ?reasonText ;
206
+ log:outputString "\n\n" .
207
+ } .
208
+
209
+ # -----------
210
+ # Check block
211
+ # -----------
212
+
213
+ { :case :status "ok" .
214
+ :case :givensPreserved ?c1 ;
215
+ :noBlanks ?c2 ;
216
+ :rowsComplete ?c3 ;
217
+ :colsComplete ?c4 ;
218
+ :boxesComplete ?c5 ;
219
+ :replayLegal ?c6 ;
220
+ :storyConsistent ?c7 .
221
+ ( "C1 %s - every given clue is preserved in the final grid.\n" ?c1 ) string:format ?l1 .
222
+ ( "C2 %s - the final grid contains only digits 1 through 9, with no blanks left.\n" ?c2 ) string:format ?l2 .
223
+ ( "C3 %s - each row contains every digit exactly once.\n" ?c3 ) string:format ?l3 .
224
+ ( "C4 %s - each column contains every digit exactly once.\n" ?c4 ) string:format ?l4 .
225
+ ( "C5 %s - each 3×3 box contains every digit exactly once.\n" ?c5 ) string:format ?l5 .
226
+ ( "C6 %s - replaying the recorded placements from the original puzzle remains legal at every step.\n" ?c6 ) string:format ?l6 .
227
+ ( "C7 %s - the search statistics and the successful proof path are internally consistent.\n" ?c7 ) string:format ?l7 .
228
+ }
229
+ => {
230
+ :03-check log:outputString "=== Check ===\n" ;
231
+ log:outputString ?l1 ;
232
+ log:outputString ?l2 ;
233
+ log:outputString ?l3 ;
234
+ log:outputString ?l4 ;
235
+ log:outputString ?l5 ;
236
+ log:outputString ?l6 ;
237
+ log:outputString ?l7 .
238
+ } .
239
+
240
+ { :case :status "ok" .
241
+ :case :unique true .
242
+ }
243
+ => { :03a-check log:outputString "C8 OK - a second search found no alternative solution, so the solution is unique.\n" . } .
244
+
245
+ { :case :status "ok" .
246
+ :case :unique false .
247
+ }
248
+ => { :03a-check log:outputString "C8 INFO - a second search found another solution, so the puzzle is not unique.\n" . } .
249
+
250
+ { :case :status "illegal-clues" . }
251
+ => { :03-check log:outputString "=== Check ===\nC1 failed - the given clues already violate Sudoku rules.\n" . } .
252
+
253
+ { :case :status "invalid-input" . }
254
+ => { :03-check log:outputString "=== Check ===\nC1 failed - the supplied text does not normalize to exactly 81 legal Sudoku cells.\n" . } .
255
+
256
+ { :case :status "unsatisfiable" . }
257
+ => { :03-check log:outputString "=== Check ===\nC1 OK - the given clues are internally consistent.\nC2 OK - every explored assignment respected row, column, and box legality.\nC3 failed - exhaustive search found no complete legal grid.\n" . } .