eyeling 1.17.1 → 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.
package/HANDBOOK.md CHANGED
@@ -1870,28 +1870,162 @@ That’s the whole engine in miniature: unify, compose substitutions, emit head
1870
1870
 
1871
1871
  Eyeling is small, which makes it pleasant to extend — but there are a few invariants worth respecting.
1872
1872
 
1873
- ### 16.1 Adding a builtin
1873
+ The most important update is architectural: **you no longer need to patch `lib/builtins.js` just to add a project-specific builtin**. The preferred path is now to load a custom builtin module, either programmatically or from the CLI. Core builtins still live in `lib/builtins.js`, but user extensions can stay outside the engine.
1874
1874
 
1875
- Most extensions belong in `lib/builtins.js` (inside `evalBuiltin`):
1875
+ ### 16.1 The preferred path: custom builtin modules
1876
1876
 
1877
- - Decide if your builtin is:
1878
- - a test (0/1 solution)
1879
- - functional (bind output)
1880
- - generator (many solutions)
1881
- - Return _deltas_ `{ varName: Term }`, not full substitutions.
1882
- - Be cautious with fully-unbound cases: generators can explode the search space.
1883
- - If you add a _new predicate_ (not just a new case inside an existing namespace), make sure it is recognized by `isBuiltinPred(...)`.
1877
+ Eyeling now exposes a small custom-builtin registry.
1884
1878
 
1885
- A small architectural note: `lib/builtins.js` is initialized by the engine via `makeBuiltins(deps)`. It receives hooks (unification, proving, deref, scoped-closure helpers, …) instead of importing the engine directly, which keeps the module graph acyclic and makes browser bundling easier.
1879
+ At runtime, builtin predicates can be added with:
1880
+
1881
+ - `registerBuiltin(iri, handler)`
1882
+ - `unregisterBuiltin(iri)`
1883
+ - `registerBuiltinModule(moduleExport, origin?)`
1884
+ - `loadBuiltinModule(specifier, { resolveFrom? })`
1885
+ - `listBuiltinIris()`
1886
+
1887
+ That means the extension story is:
1888
+
1889
+ - keep the engine’s shipped builtins in `lib/builtins.js`
1890
+ - keep your own application or domain builtins in a separate `.js` module
1891
+ - load that module with `--builtin` or from JavaScript
1892
+
1893
+ This is the safest way to extend Eyeling because it avoids forking the builtin dispatcher and keeps upgrades merge-friendly.
1894
+
1895
+ ### 16.2 CLI loading: `--builtin`
1896
+
1897
+ The CLI accepts a repeatable `--builtin <module.js>` option:
1898
+
1899
+ ```bash
1900
+ eyeling --builtin ./hello-builtin.js rules.n3
1901
+ ```
1902
+
1903
+ You can pass it more than once:
1904
+
1905
+ ```bash
1906
+ eyeling --builtin ./math-extra.js --builtin ./domain-rules.js input.n3
1907
+ ```
1908
+
1909
+ Each module is loaded before reasoning starts. Paths are resolved from the current working directory.
1910
+
1911
+ The same capability is available through the npm wrapper:
1912
+
1913
+ ```js
1914
+ const { reason } = require('eyeling');
1915
+ const out = reason({ builtinModules: ['./hello-builtin.js'] }, n3Text);
1916
+ ```
1917
+
1918
+ ### 16.3 What a builtin module may export
1919
+
1920
+ Eyeling accepts three module shapes.
1921
+
1922
+ #### A function export
1923
+
1924
+ ```js
1925
+ module.exports = ({ registerBuiltin, internLiteral, unifyTerm, terms }) => {
1926
+ const { Var } = terms;
1927
+
1928
+ registerBuiltin('http://example.org/custom#hello', ({ goal, subst }) => {
1929
+ const lit = internLiteral('"world"');
1930
+ if (goal.o instanceof Var) {
1931
+ return [{ ...subst, [goal.o.name]: lit }];
1932
+ }
1933
+ const s2 = unifyTerm(goal.o, lit, subst);
1934
+ return s2 ? [s2] : [];
1935
+ });
1936
+ };
1937
+ ```
1938
+
1939
+ #### An object with `register(api)`
1940
+
1941
+ ```js
1942
+ module.exports = {
1943
+ register(api) {
1944
+ api.registerBuiltin('http://example.org/custom#ping', ({ subst }) => [subst]);
1945
+ },
1946
+ };
1947
+ ```
1948
+
1949
+ #### A plain object mapping predicate IRIs to handlers
1950
+
1951
+ ```js
1952
+ module.exports = {
1953
+ 'http://example.org/custom#ok': ({ subst }) => [subst],
1954
+ };
1955
+ ```
1956
+
1957
+ If none of those shapes match, Eyeling rejects the module with a descriptive error.
1958
+
1959
+ ### 16.4 The handler contract
1960
+
1961
+ Builtin handlers are called with a context object like:
1962
+
1963
+ - `iri` — the predicate IRI string
1964
+ - `goal` — the current triple goal
1965
+ - `subst` — the current substitution
1966
+ - `facts`, `backRules`, `depth`, `varGen`, `maxResults`
1967
+ - `api` — the same registration/helper API used by modules
1968
+
1969
+ A handler returns **an array of substitutions**:
1970
+
1971
+ - `[]` means failure / no solutions
1972
+ - `[subst2]` means one successful continuation
1973
+ - multiple substitutions mean a generator builtin
1974
+
1975
+ In practice:
1976
+
1977
+ - Decide if your builtin is a test, a functional relation, or a generator.
1978
+ - Return substitutions (or substitution deltas merged into the current substitution), not printed output.
1979
+ - Be cautious with fully-unbound generators: they can explode the search space.
1980
+ - If a builtin needs inputs to be bound first, it is fine to fail early and let forward-rule proving retry later in the conjunction.
1981
+
1982
+ Custom builtin failures are wrapped so the predicate IRI appears in the thrown error message, which makes debugging much easier from the CLI.
1983
+
1984
+ ### 16.5 The helper API exposed to builtin modules
1985
+
1986
+ Builtin modules do not need to import internal engine files directly. Eyeling passes a helper API into module registration, including:
1987
+
1988
+ - registration helpers: `registerBuiltin`, `unregisterBuiltin`, `listBuiltinIris`
1989
+ - term constructors via `terms` (`Literal`, `Iri`, `Var`, `Blank`, `ListTerm`, `GraphTerm`, `Triple`, `Rule`, ...)
1990
+ - literal/term helpers such as `internLiteral`, `internIri`, `literalParts`, `termToN3`, `termToJsString`
1991
+ - reasoning helpers such as `unifyTerm`, `applySubstTerm`, `applySubstTriple`, `proveGoals`
1992
+ - namespace constants via `ns`
1993
+
1994
+ That API keeps the extension boundary explicit: custom builtins get the operations they need without reaching into Eyeling’s private module graph.
1995
+
1996
+ ### 16.6 A shipped example: the Sudoku builtin
1997
+
1998
+ The repository now ships a Sudoku builtin module (`lib/builtin-sudoku.js`) and a matching example program (`sudoku.n3`).
1999
+
2000
+ So this works out of the box:
2001
+
2002
+ ```bash
2003
+ eyeling sudoku.n3
2004
+ ```
2005
+
2006
+ That example is useful for two reasons:
2007
+
2008
+ - it shows a realistic domain-specific builtin implemented outside the core builtin switchboard
2009
+ - it demonstrates the intended deployment model for larger custom relations: keep the N3 logic in the `.n3` file, and keep specialized search/verification code in a loadable builtin module
2010
+
2011
+ ### 16.7 When you should still edit `lib/builtins.js`
2012
+
2013
+ Editing `lib/builtins.js` is still reasonable when you are:
2014
+
2015
+ - adding or fixing a **core** Eyeling builtin
2016
+ - changing builtin behavior that should ship as part of Eyeling itself
2017
+ - modifying the builtin helper API that custom modules depend on
2018
+
2019
+ But if the builtin is project-specific, experimental, or domain-bound, prefer a custom module first.
2020
+
2021
+ A small architectural note: `lib/builtins.js` is still initialized by the engine via `makeBuiltins(deps)`. It receives hooks (unification, proving, deref, scoped-closure helpers, …) instead of importing the engine directly, which keeps the module graph acyclic and makes browser bundling easier.
1886
2022
 
1887
2023
  If your builtin needs a stable view of the scoped closure, follow the scoped-builtin pattern:
1888
2024
 
1889
2025
  - read from `facts.__scopedSnapshot`
1890
2026
  - honor `facts.__scopedClosureLevel` and priority gating
1891
2027
 
1892
- And if your builtin is “forward-only” (needs inputs bound), it’s fine to **fail early** until inputs are available — forward rule proving enables builtin deferral, so the goal can be retried later in the same conjunction.
1893
-
1894
- ### 16.2 Adding new term shapes
2028
+ ### 16.8 Adding new term shapes
1895
2029
 
1896
2030
  If you add a new Term subclass, you’ll likely need to touch:
1897
2031
 
@@ -1900,7 +2034,7 @@ If you add a new Term subclass, you’ll likely need to touch:
1900
2034
  - variable collection for compaction (`gcCollectVarsInTerm`)
1901
2035
  - groundness checks
1902
2036
 
1903
- ### 16.3 Parser extensions
2037
+ ### 16.9 Parser extensions
1904
2038
 
1905
2039
  If you extend parsing, preserve the Rule invariants:
1906
2040
 
@@ -1983,6 +2117,7 @@ Options:
1983
2117
 
1984
2118
  ```
1985
2119
  -a, --ast Print parsed AST as JSON and exit.
2120
+ --builtin <module.js> Load a custom builtin module (repeatable).
1986
2121
  -d, --deterministic-skolem Make log:skolem stable across reasoning runs.
1987
2122
  -e, --enforce-https Rewrite http:// IRIs to https:// for log dereferencing builtins.
1988
2123
  -h, --help Show this help and exit.
@@ -2037,10 +2172,23 @@ See also:
2037
2172
 
2038
2173
  Eyeling supports a built-in “standard library” across namespaces like `log:`, `math:`, `string:`, `list:`, `time:`, `crypto:`.
2039
2174
 
2175
+ It also supports **custom builtin modules**.
2176
+
2177
+ - From the CLI: `eyeling --builtin ./my-builtins.js input.n3`
2178
+ - From JavaScript: `reason({ builtinModules: ['./my-builtins.js'] }, input)`
2179
+ - Programmatically in-process: `registerBuiltin(...)`, `registerBuiltinModule(...)`, `loadBuiltinModule(...)`
2180
+
2181
+ A concrete shipped example is the Sudoku builtin and the root-level `sudoku.n3` program:
2182
+
2183
+ ```bash
2184
+ eyeling sudoku.n3
2185
+ ```
2186
+
2040
2187
  References:
2041
2188
 
2042
2189
  - W3C N3 Built-ins overview: [https://w3c.github.io/N3/reports/20230703/builtins.html](https://w3c.github.io/N3/reports/20230703/builtins.html)
2043
2190
  - Eyeling implementation details: [Chapter 11 — Built-ins as a standard library](#ch11)
2191
+ - Extension API and custom module loading: [Chapter 16 — Extending Eyeling (without breaking it)](#ch16)
2044
2192
  - The shipped builtin catalogue: `eyeling-builtins.ttl` (in this repo)
2045
2193
 
2046
2194
  If you are running untrusted inputs, consider `--super-restricted` to disable all builtins except implication.
@@ -0,0 +1,219 @@
1
+ # ============================================================================
2
+ # BMI — ARC-style Body Mass Index example.
3
+ #
4
+ # This example turns a familiar health calculation into a small, inspectable
5
+ # ARC program. It normalizes either metric or US inputs, computes BMI, assigns
6
+ # a WHO adult category, and derives a healthy-range weight band for the given
7
+ # height. The report explains the result and includes independent checks for
8
+ # boundary handling and category behavior.
9
+ #
10
+ # For reproducibility and documentation only; not medical advice.
11
+ # ============================================================================
12
+
13
+ @prefix : <https://example.org/bmi#> .
14
+ @prefix log: <http://www.w3.org/2000/10/swap/log#> .
15
+ @prefix math: <http://www.w3.org/2000/10/swap/math#> .
16
+ @prefix string: <http://www.w3.org/2000/10/swap/string#> .
17
+
18
+ # --------------
19
+ # Editable input
20
+ # --------------
21
+
22
+ :Input
23
+ :unitSystem "metric";
24
+ :weight 72.0;
25
+ :height 178.0.
26
+
27
+ # US alternative:
28
+ # :Input
29
+ # :unitSystem "us";
30
+ # :weight 158.73;
31
+ # :height 70.08.
32
+
33
+ # ---------------------------------
34
+ # Normalization and BMI calculation
35
+ # ---------------------------------
36
+
37
+ { :Input :unitSystem "metric"; :weight ?W; :height ?H.
38
+ (?H 100.0) math:quotient ?M. }
39
+ =>
40
+ { :Case :weightKg ?W; :heightM ?M.
41
+ :Reason :units "Inputs were already metric, so kilograms stay kilograms and centimeters are divided by 100 to obtain meters.". } .
42
+
43
+ { :Input :unitSystem "us"; :weight ?W; :height ?H.
44
+ (?W 0.45359237) math:product ?Kg.
45
+ (?H 0.0254) math:product ?M. }
46
+ =>
47
+ { :Case :weightKg ?Kg; :heightM ?M.
48
+ :Reason :units "US inputs were converted to SI units: pounds to kilograms and inches to meters.". } .
49
+
50
+ { :Case :weightKg ?Kg; :heightM ?M.
51
+ (?M ?M) math:product ?M2.
52
+ (?Kg ?M2) math:quotient ?Bmi.
53
+ (?Bmi 100.0) math:product ?BmiX100.
54
+ ?BmiX100 math:rounded ?BmiRoundedInt.
55
+ (?BmiRoundedInt 100.0) math:quotient ?BmiRounded.
56
+ (18.5 ?M2) math:product ?HealthyMin.
57
+ (24.9 ?M2) math:product ?HealthyMax.
58
+ (?HealthyMin 10.0) math:product ?MinX10.
59
+ (?HealthyMax 10.0) math:product ?MaxX10.
60
+ ?MinX10 math:rounded ?MinRoundedInt.
61
+ ?MaxX10 math:rounded ?MaxRoundedInt.
62
+ (?MinRoundedInt 10.0) math:quotient ?HealthyMinRounded.
63
+ (?MaxRoundedInt 10.0) math:quotient ?HealthyMaxRounded. }
64
+ =>
65
+ { :Case :heightSquared ?M2;
66
+ :bmi ?Bmi;
67
+ :bmiRounded ?BmiRounded;
68
+ :healthyMinKg ?HealthyMin;
69
+ :healthyMaxKg ?HealthyMax;
70
+ :healthyMinKgRounded ?HealthyMinRounded;
71
+ :healthyMaxKgRounded ?HealthyMaxRounded. } .
72
+
73
+ # ------------------------------------------
74
+ # WHO adult categories (half-open intervals)
75
+ # ------------------------------------------
76
+
77
+ { :Case :bmi ?Bmi. ?Bmi math:lessThan 18.5. }
78
+ => { :Decision :category "Underweight". } .
79
+
80
+ { :Case :bmi ?Bmi. ?Bmi math:notLessThan 18.5. ?Bmi math:lessThan 25.0. }
81
+ => { :Decision :category "Normal". } .
82
+
83
+ { :Case :bmi ?Bmi. ?Bmi math:notLessThan 25.0. ?Bmi math:lessThan 30.0. }
84
+ => { :Decision :category "Overweight". } .
85
+
86
+ { :Case :bmi ?Bmi. ?Bmi math:notLessThan 30.0. ?Bmi math:lessThan 35.0. }
87
+ => { :Decision :category "Obesity I". } .
88
+
89
+ { :Case :bmi ?Bmi. ?Bmi math:notLessThan 35.0. ?Bmi math:lessThan 40.0. }
90
+ => { :Decision :category "Obesity II". } .
91
+
92
+ { :Case :bmi ?Bmi. ?Bmi math:notLessThan 40.0. }
93
+ => { :Decision :category "Obesity III". } .
94
+
95
+ # ---------------------
96
+ # Answer and reason why
97
+ # ---------------------
98
+
99
+ { :Case :bmiRounded ?BmiRounded;
100
+ :healthyMinKgRounded ?HealthyMinRounded;
101
+ :healthyMaxKgRounded ?HealthyMaxRounded;
102
+ :heightM ?M.
103
+ :Decision :category ?Category.
104
+ (?M 100.0) math:product ?Cm.
105
+ ?Cm math:rounded ?CmRounded. }
106
+ =>
107
+ { :Answer :bmi ?BmiRounded;
108
+ :category ?Category;
109
+ :healthyMinKg ?HealthyMinRounded;
110
+ :healthyMaxKg ?HealthyMaxRounded;
111
+ :heightCm ?CmRounded. } .
112
+
113
+ { :Case :weightKg ?Kg; :heightM ?M; :heightSquared ?M2; :bmiRounded ?BmiRounded.
114
+ :Reason :units ?Units.
115
+ :Decision :category ?Category. }
116
+ =>
117
+ { :Reason :formula "BMI is defined as weight in kilograms divided by height in meters squared.";
118
+ :calculation "The normalized weight and height were used to compute BMI, then the result was mapped to the WHO adult category table.";
119
+ :categoryRule ?Category;
120
+ :unitsExplanation ?Units. } .
121
+
122
+ # ------------------
123
+ # Independent checks
124
+ # ------------------
125
+
126
+ { :Case :weightKg ?Kg; :heightM ?M. ?Kg math:greaterThan 0. ?M math:greaterThan 0. }
127
+ => { :Check :c1 "OK - the input was normalized into positive SI values.". } .
128
+
129
+ { :Case :heightM ?M; :heightSquared ?M2. (?M ?M) math:product ?M2. }
130
+ => { :Check :c2 "OK - height squared was reconstructed from the normalized height.". } .
131
+
132
+ { :Case :weightKg ?Kg; :heightSquared ?M2; :bmi ?Bmi. (?Kg ?M2) math:quotient ?Bmi. }
133
+ => { :Check :c3 "OK - the BMI value matches the BMI = kg / m² formula.". } .
134
+
135
+ { 18.49 math:lessThan 18.5. }
136
+ => { :Check :c4 "OK - a BMI of 18.49 stays below the normal-weight threshold.". } .
137
+
138
+ { 18.5 math:notLessThan 18.5. 18.5 math:lessThan 25.0. }
139
+ => { :Check :c5 "OK - the lower boundary is half-open: BMI 18.5 is classified as Normal.". } .
140
+
141
+ { 25.0 math:notLessThan 25.0. 25.0 math:lessThan 30.0. }
142
+ => { :Check :c6 "OK - BMI 25.0 starts the Overweight category.". } .
143
+
144
+ { 30.0 math:notLessThan 30.0. 30.0 math:lessThan 35.0. }
145
+ => { :Check :c7 "OK - BMI 30.0 starts the Obesity I category.". } .
146
+
147
+ { 22.0 math:notLessThan 18.5. 22.0 math:lessThan 25.0.
148
+ 27.0 math:notLessThan 25.0. 27.0 math:lessThan 30.0.
149
+ 41.0 math:notLessThan 40.0. }
150
+ => { :Check :c8 "OK - classification behavior is monotonic across representative BMI values.". } .
151
+
152
+ { :Case :heightSquared ?M2; :healthyMinKg ?Min; :healthyMaxKg ?Max.
153
+ (18.5 ?M2) math:product ?Min.
154
+ (24.9 ?M2) math:product ?Max. }
155
+ => { :Check :c9 "OK - the healthy-weight band was reconstructed from BMI 18.5 to 24.9 at the same height.". } .
156
+
157
+ # -----
158
+ # Fuses
159
+ # -----
160
+
161
+ { :Decision :category ?Any.
162
+ 1 log:notIncludes {
163
+ :Check :c1 ?C1.
164
+ :Check :c2 ?C2.
165
+ :Check :c3 ?C3.
166
+ :Check :c4 ?C4.
167
+ :Check :c5 ?C5.
168
+ :Check :c6 ?C6.
169
+ :Check :c7 ?C7.
170
+ :Check :c8 ?C8.
171
+ :Check :c9 ?C9.
172
+ }. }
173
+ => false .
174
+
175
+ { :Decision :category ?C1, ?C2.
176
+ ?C1 log:notEqualTo ?C2. }
177
+ => false .
178
+
179
+ # ---------------------------------------------
180
+ # ARC report (built from actual derived values)
181
+ # ---------------------------------------------
182
+
183
+ { :Answer :bmi ?BmiRounded;
184
+ :category ?Category;
185
+ :healthyMinKg ?HealthyMinRounded;
186
+ :healthyMaxKg ?HealthyMaxRounded;
187
+ :heightCm ?CmRounded.
188
+ :Check :c1 ?C1.
189
+ :Check :c2 ?C2.
190
+ :Check :c3 ?C3.
191
+ :Check :c4 ?C4.
192
+ :Check :c5 ?C5.
193
+ :Check :c6 ?C6.
194
+ :Check :c7 ?C7.
195
+ :Check :c8 ?C8.
196
+ :Check :c9 ?C9.
197
+ (
198
+ "BMI — ARC-style Body Mass Index example\n\n"
199
+ "Answer\n"
200
+ "BMI = " ?BmiRounded "\n"
201
+ "Category = " ?Category "\n"
202
+ "At height " ?CmRounded " cm, a healthy-weight range is about " ?HealthyMinRounded "–" ?HealthyMaxRounded " kg (BMI 18.5–24.9).\n\n"
203
+ "Reason Why\n"
204
+ "BMI is defined as weight in kilograms divided by height in meters squared. "
205
+ "This program first normalizes the input to SI units, computes BMI, and then applies WHO adult categories as half-open intervals. "
206
+ "The healthy-weight band is the weight range at the same height that corresponds to BMI 18.5 through 24.9.\n\n"
207
+ "Check\n"
208
+ "C1 " ?C1 "\n"
209
+ "C2 " ?C2 "\n"
210
+ "C3 " ?C3 "\n"
211
+ "C4 " ?C4 "\n"
212
+ "C5 " ?C5 "\n"
213
+ "C6 " ?C6 "\n"
214
+ "C7 " ?C7 "\n"
215
+ "C8 " ?C8 "\n"
216
+ "C9 " ?C9 "\n"
217
+ ) string:concatenation ?Block. }
218
+ =>
219
+ { :report log:outputString ?Block. } .
@@ -0,0 +1,20 @@
1
+ BMI — ARC-style Body Mass Index example
2
+
3
+ Answer
4
+ BMI = 22.72
5
+ Category = Normal
6
+ At height 178 cm, a healthy-weight range is about 58.6–78.9 kg (BMI 18.5–24.9).
7
+
8
+ Reason Why
9
+ BMI is defined as weight in kilograms divided by height in meters squared. This program first normalizes the input to SI units, computes BMI, and then applies WHO adult categories as half-open intervals. The healthy-weight band is the weight range at the same height that corresponds to BMI 18.5 through 24.9.
10
+
11
+ Check
12
+ C1 OK - the input was normalized into positive SI values.
13
+ C2 OK - height squared was reconstructed from the normalized height.
14
+ C3 OK - the BMI value matches the BMI = kg / m² formula.
15
+ C4 OK - a BMI of 18.49 stays below the normal-weight threshold.
16
+ C5 OK - the lower boundary is half-open: BMI 18.5 is classified as Normal.
17
+ C6 OK - BMI 25.0 starts the Overweight category.
18
+ C7 OK - BMI 30.0 starts the Obesity I category.
19
+ C8 OK - classification behavior is monotonic across representative BMI values.
20
+ C9 OK - the healthy-weight band was reconstructed from BMI 18.5 to 24.9 at the same height.
@@ -0,0 +1,23 @@
1
+ === Answer ===
2
+ 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.
3
+ case : pn-junction-tunneling
4
+ peak bias : 2
5
+ peak current proxy : 4
6
+ negative differential region : yes
7
+
8
+ === Reason Why ===
9
+ 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.
10
+ ordinary depletion width (nm) : 8
11
+ tunnel depletion width (nm) : 1
12
+ filled N-side states : [1, 2, 3, 4]
13
+ empty P-side states at 0 bias : [3, 4, 5, 6]
14
+ bias -> overlap current proxy : 0->2, 1->3, 2->4, 3->3, 4->2, 5->1, 6->0
15
+ peak point : 2 -> 4
16
+ high-bias point : 6 -> 0
17
+
18
+ === Check ===
19
+ heavily doped barrier is narrower : yes
20
+ peak occurs before overlap closes : yes
21
+ negative differential region present : yes
22
+ high-bias overlap closes : yes
23
+ peak equals full four-state overlap: yes
@@ -10,11 +10,11 @@ Reason Why
10
10
  The plan resolved the person's address, turned it into a map point, checked the local weather, selected a suitable restaurant, and then created a reservation. Because the weather came back mild and stable (22 C and 1016 mbar), the chosen seating stayed outdoors.
11
11
 
12
12
  Check
13
- C1 address resolved.
14
- C2 location found.
15
- C3 weather loaded.
16
- C4 outdoor dining justified.
17
- C5 reservable restaurant selected.
18
- C6 requested date preserved.
19
- C7 outdoor preference preserved.
20
- C8 original goal pattern satisfied.
13
+ C1 OK - the preferences service resolved the person's address.
14
+ C2 OK - the location service turned the address into map coordinates.
15
+ C3 OK - the weather services supplied temperature and pressure for that location.
16
+ C4 OK - the weather interpretation justified outdoor seating.
17
+ C5 OK - the recommendation step selected a restaurant that can accept reservations.
18
+ C6 OK - the reservation preserved the requested dinner date.
19
+ C7 OK - the reservation preserved the outdoor seating preference.
20
+ C8 OK - the final goal pattern from the original RESTdesc query is satisfied.
@@ -0,0 +1,42 @@
1
+ === Answer ===
2
+ The puzzle is solved, and the completed grid is the unique valid Sudoku solution.
3
+ case : sudoku
4
+ default puzzle : classic
5
+
6
+ Puzzle
7
+ 1 . . | . . 7 | . 9 .
8
+ . 3 . | . 2 . | . . 8
9
+ . . 9 | 6 . . | 5 . .
10
+
11
+ . . 5 | 3 . . | 9 . .
12
+ . 1 . | . 8 . | . . 2
13
+ 6 . . | . . 4 | . . .
14
+
15
+ 3 . . | . . . | . 1 .
16
+ . 4 . | . . . | . . 7
17
+ . . 7 | . . . | 3 . .
18
+
19
+ Completed grid
20
+ 1 6 2 | 8 5 7 | 4 9 3
21
+ 5 3 4 | 1 2 9 | 6 7 8
22
+ 7 8 9 | 6 4 3 | 5 2 1
23
+
24
+ 4 7 5 | 3 1 2 | 9 8 6
25
+ 9 1 3 | 5 8 6 | 7 4 2
26
+ 6 2 8 | 7 9 4 | 1 3 5
27
+
28
+ 3 5 6 | 4 7 8 | 2 1 9
29
+ 2 4 1 | 9 3 5 | 8 6 7
30
+ 8 9 7 | 2 6 1 | 3 5 4
31
+ === Reason Why ===
32
+ The solver starts from 23 clues and fills the remaining 58 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 213 forced placements and tried 22 guesses, visited 23 search nodes overall, and backtracked 12 times before reaching the completed grid. The solver also confirmed that the solution is unique. Early steps: r2c3=4: guess, r5c3=3: forced, r2c1=5: guess, r2c4=1: guess, r2c6=9: forced, r2c7=6: guess, r2c8=7: forced, r1c7=4: guess, … and 50 more placements
33
+
34
+ === Check ===
35
+ C1 OK - every given clue is preserved in the final grid.
36
+ C2 OK - the final grid contains only digits 1 through 9, with no blanks left.
37
+ C3 OK - each row contains every digit exactly once.
38
+ C4 OK - each column contains every digit exactly once.
39
+ C5 OK - each 3×3 box contains every digit exactly once.
40
+ C6 OK - replaying the recorded placements from the original puzzle remains legal at every step.
41
+ C7 OK - the search statistics and the successful proof path are internally consistent.
42
+ C8 OK - a second search found no alternative solution, so the solution is unique.
@@ -0,0 +1,24 @@
1
+ === Answer ===
2
+ In this toy transistor-switch model, a low input leaves the transistor in cutoff (OFF) and a high input drives it into saturation (ON), so the load behaves like an on/off branch rather than a linear amplifier.
3
+ case : transistor-switch
4
+ low input state : cutoff / OFF
5
+ high input state : saturation / ON
6
+ on-state load current : 4.80 mA
7
+
8
+ === Reason Why ===
9
+ We model an NPN low-side switch with exact millivolt and microamp arithmetic. The base current comes from (Vin - Vbe,on)/Rb when the base-emitter junction is forward biased, and the collector current is the smaller of beta * Ib and the load-limited current (Vcc - Vce,sat)/Rl.
10
+ supply voltage : 5.00 V
11
+ base resistor : 10000 ohms
12
+ load resistor : 1000 ohms
13
+ transistor beta proxy : 100
14
+ low input : Vin=0.00 V -> Ib=0.00 mA, Ic=0.00 mA, Vce=5.00 V, state=cutoff / OFF
15
+ high input : Vin=5.00 V -> Ib=0.43 mA, Ic=4.80 mA, Vce=0.20 V, state=saturation / ON
16
+ high-input gain limit : 43.00 mA
17
+ high-input load limit : 4.80 mA
18
+
19
+ === Check ===
20
+ low input stays in cutoff : yes
21
+ high input reaches saturation : yes
22
+ switching states differ : yes
23
+ on-state current is load-limited : yes
24
+ load voltage matches resistor drop : yes