eyeling 1.14.13 → 1.15.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.
Files changed (29) hide show
  1. package/examples/check/input/deep-taxonomy-100000.c +20 -0
  2. package/examples/check/input/gps.c +127 -0
  3. package/examples/check/input/high-trust-rdf-bloom-envelope.c +148 -0
  4. package/examples/check/input/high-trust-rdf-bloom-tamper-contrast.c +247 -0
  5. package/examples/check/input/odrl-dpv-risk-ranked.c +275 -0
  6. package/examples/check/output/deep-taxonomy-100000.n3 +300004 -0
  7. package/examples/check/output/gps.n3 +6 -0
  8. package/examples/check/output/high-trust-rdf-bloom-envelope.n3 +7 -0
  9. package/examples/check/output/high-trust-rdf-bloom-tamper-contrast.n3 +27 -0
  10. package/examples/check/output/odrl-dpv-risk-ranked.n3 +13 -0
  11. package/examples/decimal-ebike-motor-thermal-envelope.n3 +286 -0
  12. package/examples/decimal-transcendental-servo-envelope.n3 +197 -0
  13. package/examples/deck/high-trust-rdf-bloom-envelope.md +371 -0
  14. package/examples/deck/schema-foaf-mapping.md +3 -1
  15. package/examples/high-trust-rdf-bloom-envelope.n3 +281 -0
  16. package/examples/high-trust-rdf-bloom-tamper-contrast.n3 +395 -0
  17. package/examples/integer-first-control-tank-level.n3 +209 -0
  18. package/examples/integer-first-sqrt2-mediants.n3 +174 -0
  19. package/examples/output/decimal-ebike-motor-thermal-envelope.n3 +25 -0
  20. package/examples/output/decimal-transcendental-servo-envelope.n3 +29 -0
  21. package/examples/output/high-trust-rdf-bloom-envelope.n3 +7 -0
  22. package/examples/output/high-trust-rdf-bloom-tamper-contrast.n3 +27 -0
  23. package/examples/output/integer-first-control-tank-level.n3 +70 -0
  24. package/examples/output/integer-first-sqrt2-mediants.n3 +57 -0
  25. package/eyeling.js +90 -1
  26. package/lib/lexer.js +90 -1
  27. package/package.json +3 -2
  28. package/test/api.test.js +221 -0
  29. package/test/check.test.js +174 -0
@@ -0,0 +1,6 @@
1
+ @prefix : <https://eyereasoner.github.io/eye/reasoning#> .
2
+ @prefix gps: <https://eyereasoner.github.io/eye/reasoning/gps/gps-schema#> .
3
+ @prefix xsd: <http://www.w3.org/2001/XMLSchema#> .
4
+
5
+ :i1 gps:path ((:drive_gent_brugge :drive_brugge_oostende) "2400"^^xsd:decimal "0.01"^^xsd:decimal "0.9408"^^xsd:decimal "0.99"^^xsd:decimal) .
6
+ :i1 gps:path ((:drive_gent_kortrijk :drive_kortrijk_brugge :drive_brugge_oostende) "4100"^^xsd:decimal "0.018"^^xsd:decimal "0.903168"^^xsd:decimal "0.9801"^^xsd:decimal) .
@@ -0,0 +1,7 @@
1
+ @prefix : <http://example.org/high-trust-rdf#> .
2
+ @prefix xsd: <http://www.w3.org/2001/XMLSchema#> .
3
+
4
+ :result :expIntervalCertificate :CertifiedDecimalInterval .
5
+ :result :summary ("parameter-sanity" true "index-agreement" true "transcendental" "exp(-k*n/m)" "lambda" "0.5126953125"^^xsd:decimal "certified-lambda" 0.5126953125 "exp-lower" 0.5988792348 "exp-upper" 0.5988792349 "fp-lower" "0.0016708059567271017"^^xsd:decimal "fp-upper" "0.0016708059596428394"^^xsd:decimal "expected-extra-exact-lookups-upper" "83.54029798214196"^^xsd:decimal "decision" :AcceptForHighTrustUse) .
6
+ :result :withinExactLookupBudget true .
7
+ :result :withinFpRateBudget true .
@@ -0,0 +1,27 @@
1
+ @prefix : <http://example.org/high-trust-rdf#> .
2
+ @prefix xsd: <http://www.w3.org/2001/XMLSchema#> .
3
+
4
+ :result :decision [
5
+ :artifact :trustedArtifact ;
6
+ :hardened :AcceptForHighTrustUse ;
7
+ :weak :AcceptUnderWeakBudgetOnlyRules
8
+ ] .
9
+ :result :decision [
10
+ :artifact :tamperedArtifact ;
11
+ :hardened :RejectForHighTrustUse ;
12
+ :weak :AcceptUnderWeakBudgetOnlyRules
13
+ ] .
14
+ :result :rejectReason [
15
+ :artifact :tamperedArtifact ;
16
+ :why :NonPositiveBloomBits
17
+ ] .
18
+ :result :rejectReason [
19
+ :artifact :tamperedArtifact ;
20
+ :why :CertifiedLambdaMismatch
21
+ ] .
22
+ :result :rejectReason [
23
+ :artifact :tamperedArtifact ;
24
+ :why :MalformedIntervalOrdering
25
+ ] .
26
+ :result :summary (:tamperedArtifact "lambda" -700 "certified-lambda" 0.5126953125 "weak-fp-upper" "-194754273881"^^xsd:decimal "weak-extra-exact-upper" "-194754273881"^^xsd:decimal "weak-decision" :AcceptUnderWeakBudgetOnlyRules "hardened-decision" :RejectForHighTrustUse) .
27
+ :result :summary (:trustedArtifact "lambda" "0.5126953125"^^xsd:decimal "certified-lambda" 0.5126953125 "weak-fp-upper" "0.0016708059596428394"^^xsd:decimal "weak-extra-exact-upper" "83.54029798214196"^^xsd:decimal "weak-decision" :AcceptUnderWeakBudgetOnlyRules "hardened-decision" :AcceptForHighTrustUse) .
@@ -0,0 +1,13 @@
1
+ @prefix : <https://example.org/odrl-dpv-risk-ranked#> .
2
+ @prefix log: <http://www.w3.org/2000/10/swap/log#> .
3
+
4
+ (:Agreement1 :ConsumerExample 0) log:outputString "\n=== Ranked DPV Risk Report ===\nAgreement: Example Agreement\nProfile: Example consumer profile\n\n" .
5
+ (:Agreement1 :ConsumerExample 1 900 "C1" 0 _:sk_1) log:outputString "score=100 (https://w3id.org/dpv/risk#HighRisk, https://w3id.org/dpv/risk#HighSeverity) clause C1\n Risk: account/data removal is permitted without notice safeguards (no notice constraint and no duty to inform). Clause C1: Provider may remove the user account (and associated data) at its discretion.\n\n" .
6
+ (:Agreement1 :ConsumerExample 1 900 "C1" 1 _:sk_1 _:sk_2) log:outputString " - mitigation for clause C1: Add a notice constraint (minimum noticeDays) before account removal.\n" .
7
+ (:Agreement1 :ConsumerExample 1 900 "C1" 1 _:sk_1 _:sk_4) log:outputString " - mitigation for clause C1: Add a duty to inform the consumer prior to account removal.\n" .
8
+ (:Agreement1 :ConsumerExample 1 903 "C3" 0 _:sk_12) log:outputString "score=97 (https://w3id.org/dpv/risk#HighRisk, https://w3id.org/dpv/risk#HighSeverity) clause C3\n Risk: user data sharing is permitted without an explicit consent constraint. Clause C3: Provider may share user data with partners for business purposes.\n\n" .
9
+ (:Agreement1 :ConsumerExample 1 903 "C3" 1 _:sk_12 _:sk_13) log:outputString " - mitigation for clause C3: Add an explicit consent constraint before data sharing.\n" .
10
+ (:Agreement1 :ConsumerExample 1 915 "C2" 0 _:sk_7) log:outputString "score=85 (https://w3id.org/dpv/risk#HighRisk, https://w3id.org/dpv/risk#HighSeverity) clause C2\n Risk: terms may change with notice (3 days) below consumer requirement (14 days). Clause C2: Provider may change terms by informing users at least 3 days in advance.\n\n" .
11
+ (:Agreement1 :ConsumerExample 1 915 "C2" 1 _:sk_7 _:sk_8) log:outputString " - mitigation for clause C2: Increase minimum noticeDays in the inform duty to meet the consumer requirement.\n" .
12
+ (:Agreement1 :ConsumerExample 1 930 "C4" 0 _:sk_16) log:outputString "score=70 (https://w3id.org/dpv/risk#ModerateRisk, https://w3id.org/dpv/risk#ModerateSeverity) clause C4\n Risk: portability is restricted because exporting user data is prohibited. Clause C4: Users are not permitted to export their data.\n\n" .
13
+ (:Agreement1 :ConsumerExample 1 930 "C4" 1 _:sk_16 _:sk_17) log:outputString " - mitigation for clause C4: Add a permission allowing data export (or remove the prohibition) to support portability.\n" .
@@ -0,0 +1,286 @@
1
+ # ===============================================================================
2
+ # Decimal transcendental motor-thermal envelope for an e-bike climb
3
+ #
4
+ # Why this example exists:
5
+ # It shows how xsd:decimal can carry a machine-checkable certificate in an
6
+ # e-biking setting where a transcendental quantity naturally appears.
7
+ #
8
+ # Physical story:
9
+ # During a climb, an e-bike motor heats up from rider-selected assist modes,
10
+ # while also cooling toward ambient temperature.
11
+ #
12
+ # A simple sampled model for the motor temperature excess over ambient is
13
+ #
14
+ # e(k+1) = a * e(k) + g(mode(k))
15
+ #
16
+ # where
17
+ # a = exp(-Ts/tau)
18
+ #
19
+ # is the exact cooling factor, Ts is the sample period, tau is the thermal
20
+ # time constant, and g(mode) is the per-sample heat injection for the chosen
21
+ # assist mode.
22
+ #
23
+ # The transcendental part:
24
+ # For Ts = 5 s and tau = 20 s we get
25
+ #
26
+ # a = exp(-1/4)
27
+ #
28
+ # which is transcendental. We therefore do not pretend to store the exact real.
29
+ # Instead we keep a certified xsd:decimal interval
30
+ #
31
+ # 0.7788007830 <= exp(-1/4) <= 0.7788007831
32
+ #
33
+ # and propagate an exact decimal envelope for the motor temperature.
34
+ #
35
+ # Ride plan:
36
+ # * samples 0..2 : Turbo assist
37
+ # * samples 3..4 : Tour assist
38
+ # * samples 5..7 : Eco assist
39
+ # * samples 8..11 : Coast (no drive heat)
40
+ #
41
+ # What is certified:
42
+ # * the cooling interval is well-formed and contractive
43
+ # * the motor stays below the hard limit during the whole sampled ride plan
44
+ # * after the climb, the upper temperature envelope drops below the warning
45
+ # threshold again at sample 8, i.e. after 40 s
46
+ # ===============================================================================
47
+
48
+ @prefix : <http://example.org/ebike-thermal#>.
49
+ @prefix math: <http://www.w3.org/2000/10/swap/math#>.
50
+ @prefix log: <http://www.w3.org/2000/10/swap/log#>.
51
+ @prefix xsd: <http://www.w3.org/2001/XMLSchema#>.
52
+
53
+ # ----------
54
+ # Parameters
55
+ # ----------
56
+
57
+ :ride a :EBikeThermalAssessment;
58
+ :samplePeriod "5.0"^^xsd:decimal;
59
+ :thermalTimeConstant "20.0"^^xsd:decimal;
60
+ :exactCoolingSymbol "exp(-1/4)";
61
+ :coolingLower "0.7788007830"^^xsd:decimal;
62
+ :coolingUpper "0.7788007831"^^xsd:decimal;
63
+ :ambient "25.0"^^xsd:decimal;
64
+ :initialMotorTemperature "33.0"^^xsd:decimal;
65
+ :warningLimit "35.0"^^xsd:decimal;
66
+ :hardLimit "45.0"^^xsd:decimal;
67
+ :maxStep 12.
68
+
69
+ :Turbo :heatingLower "4.8"^^xsd:decimal; :heatingUpper "4.8"^^xsd:decimal.
70
+ :Tour :heatingLower "2.4"^^xsd:decimal; :heatingUpper "2.4"^^xsd:decimal.
71
+ :Eco :heatingLower "1.2"^^xsd:decimal; :heatingUpper "1.2"^^xsd:decimal.
72
+ :Coast :heatingLower "0.0"^^xsd:decimal; :heatingUpper "0.0"^^xsd:decimal.
73
+
74
+ :ride :assistAt (0 :Turbo).
75
+ :ride :assistAt (1 :Turbo).
76
+ :ride :assistAt (2 :Turbo).
77
+ :ride :assistAt (3 :Tour).
78
+ :ride :assistAt (4 :Tour).
79
+ :ride :assistAt (5 :Eco).
80
+ :ride :assistAt (6 :Eco).
81
+ :ride :assistAt (7 :Eco).
82
+ :ride :assistAt (8 :Coast).
83
+ :ride :assistAt (9 :Coast).
84
+ :ride :assistAt (10 :Coast).
85
+ :ride :assistAt (11 :Coast).
86
+
87
+ # ----------------------------------------------------------
88
+ # The decimal interval is a finite certificate for exp(-1/4)
89
+ # ----------------------------------------------------------
90
+
91
+ {
92
+ :ride :coolingLower ?lo; :coolingUpper ?hi.
93
+ ?lo math:lessThan ?hi.
94
+ ?lo math:greaterThan 0.
95
+ ?hi math:lessThan 1.
96
+ }
97
+ =>
98
+ {
99
+ :ride :coolingCertificate :CertifiedDecimalInterval.
100
+ :ride :contractiveCooling true.
101
+ }.
102
+
103
+ # ----------------
104
+ # Initial envelope
105
+ # ----------------
106
+
107
+ {
108
+ :ride :ambient ?amb; :initialMotorTemperature ?t0.
109
+ ( ?t0 ?amb ) math:difference ?e0.
110
+ }
111
+ =>
112
+ {
113
+ :ride :excessEnvelopeAt (0 ?e0 ?e0).
114
+ }.
115
+
116
+ # --------------------------------------------------------------------------
117
+ # Envelope propagation
118
+ # excessLower(k+1) = coolingLower * excessLower(k) + heatingLower(mode(k))
119
+ # excessUpper(k+1) = coolingUpper * excessUpper(k) + heatingUpper(mode(k))
120
+ # --------------------------------------------------------------------------
121
+
122
+ {
123
+ :ride :coolingLower ?aLo;
124
+ :coolingUpper ?aHi;
125
+ :maxStep ?max.
126
+ :ride :assistAt (?k ?mode).
127
+ ?mode :heatingLower ?gLo; :heatingUpper ?gHi.
128
+ :ride :excessEnvelopeAt (?k ?lo ?hi).
129
+ ?k math:lessThan ?max.
130
+ ( ?k 1 ) math:sum ?k1.
131
+ ( ?aLo ?lo ) math:product ?decayedLo.
132
+ ( ?aHi ?hi ) math:product ?decayedHi.
133
+ ( ?decayedLo ?gLo ) math:sum ?lo1.
134
+ ( ?decayedHi ?gHi ) math:sum ?hi1.
135
+ }
136
+ =>
137
+ {
138
+ :ride :excessEnvelopeAt (?k1 ?lo1 ?hi1).
139
+ }.
140
+
141
+ # ---------------------------------------------
142
+ # Convert excess-over-ambient to absolute motor
143
+ # temperature envelopes for each sample.
144
+ # ---------------------------------------------
145
+
146
+ {
147
+ :ride :ambient ?amb.
148
+ :ride :excessEnvelopeAt (?k ?lo ?hi).
149
+ ( ?amb ?lo ) math:sum ?tLo.
150
+ ( ?amb ?hi ) math:sum ?tHi.
151
+ }
152
+ =>
153
+ {
154
+ :ride :motorTemperatureEnvelopeAt (?k ?tLo ?tHi).
155
+ }.
156
+
157
+ # ------------------------
158
+ # Threshold certifications
159
+ # ------------------------
160
+
161
+ {
162
+ :ride :motorTemperatureEnvelopeAt (?k ?tLo ?tHi).
163
+ :ride :hardLimit ?lim.
164
+ ?tHi math:lessThan ?lim.
165
+ }
166
+ =>
167
+ {
168
+ :ride :belowHardLimitAt ?k.
169
+ }.
170
+
171
+ {
172
+ :ride :motorTemperatureEnvelopeAt (?k ?tLo ?tHi).
173
+ :ride :warningLimit ?lim.
174
+ ?tHi math:lessThan ?lim.
175
+ }
176
+ =>
177
+ {
178
+ :ride :belowWarningAt ?k.
179
+ }.
180
+
181
+ # ---------------------------------------------------
182
+ # Detect where the upper temperature envelope starts
183
+ # moving downward again after the harder climb phase.
184
+ # ---------------------------------------------------
185
+
186
+ {
187
+ :ride :motorTemperatureEnvelopeAt (?k ?tLo ?tHi).
188
+ ( ?k 1 ) math:sum ?k1.
189
+ :ride :motorTemperatureEnvelopeAt (?k1 ?tLo1 ?tHi1).
190
+ ?tHi1 math:lessThan ?tHi.
191
+ }
192
+ =>
193
+ {
194
+ :ride :upperEnvelopeDecreasesAt ?k.
195
+ }.
196
+
197
+ # --------------------------------------------------------
198
+ # First return below the warning limit after being at/over
199
+ # the warning limit in the previous sample.
200
+ # --------------------------------------------------------
201
+
202
+ {
203
+ :ride :belowWarningAt ?k.
204
+ ?k math:greaterThan 0.
205
+ ( ?k 1 ) math:difference ?km1.
206
+ :ride :motorTemperatureEnvelopeAt (?km1 ?prevLo ?prevHi).
207
+ :ride :warningLimit ?lim.
208
+ ?prevHi math:notLessThan ?lim.
209
+ }
210
+ =>
211
+ {
212
+ :ride :firstRecoveredWarningAt ?k.
213
+ }.
214
+
215
+ {
216
+ :ride :firstRecoveredWarningAt ?k;
217
+ :samplePeriod ?ts.
218
+ ( ?k ?ts ) math:product ?t.
219
+ }
220
+ =>
221
+ {
222
+ :ride :firstRecoveredWarningTime ?t.
223
+ }.
224
+
225
+ # ----------------------------------------------------------------------
226
+ # Acceptance argument for this fixed ride plan:
227
+ # * samples 0..3 are individually below the hard limit
228
+ # * from sample 3 onward the upper envelope decreases at every step
229
+ # * therefore all later samples stay below the sample-3 upper envelope
230
+ # * the envelope returns below the warning limit at sample 8 = 40 s
231
+ # ----------------------------------------------------------------------
232
+
233
+ {
234
+ :ride :belowHardLimitAt 0, 1, 2, 3.
235
+ :ride :upperEnvelopeDecreasesAt 3, 4, 5, 6, 7, 8, 9, 10, 11.
236
+ :ride :firstRecoveredWarningAt 8.
237
+ }
238
+ =>
239
+ {
240
+ :ride :rideDecision :ThermallySafeForThisAssistPlan.
241
+ }.
242
+
243
+ # ---------------
244
+ # Readable output
245
+ # ---------------
246
+
247
+ {
248
+ :ride :exactCoolingSymbol ?sym;
249
+ :coolingLower ?aLo;
250
+ :coolingUpper ?aHi;
251
+ :warningLimit ?warn;
252
+ :hardLimit ?hard;
253
+ :firstRecoveredWarningAt ?k;
254
+ :firstRecoveredWarningTime ?t;
255
+ :rideDecision ?decision.
256
+ }
257
+ log:query
258
+ {
259
+ :result :summary (
260
+ "cooling-symbol" ?sym
261
+ "cooling-lower" ?aLo
262
+ "cooling-upper" ?aHi
263
+ "warning-limit-C" ?warn
264
+ "hard-limit-C" ?hard
265
+ "warning-recovery-step" ?k
266
+ "warning-recovery-time-s" ?t
267
+ "decision" ?decision
268
+ ).
269
+ }.
270
+
271
+ {
272
+ :ride :assistAt (?k ?mode).
273
+ :ride :motorTemperatureEnvelopeAt (?k ?tLo ?tHi).
274
+ }
275
+ log:query
276
+ {
277
+ :result :temperatureTrace (?k ?mode ?tLo ?tHi).
278
+ }.
279
+
280
+ {
281
+ :ride :upperEnvelopeDecreasesAt ?k.
282
+ }
283
+ log:query
284
+ {
285
+ :result :coolingStep ?k.
286
+ }.
@@ -0,0 +1,197 @@
1
+ # =======================================================================================
2
+ # Decimal transcendental servo envelope
3
+ #
4
+ # Why this example exists:
5
+ # It illustrates the “integer-first” idea in a setting where a genuinely transcendental
6
+ # constant appears in control engineering.
7
+ #
8
+ # Physical story:
9
+ # A sampled first-order servo has error dynamics
10
+ #
11
+ # e(k+1) = a * e(k)
12
+ #
13
+ # with exact discrete pole
14
+ #
15
+ # a = exp(-Ts/tau) = exp(-1/3)
16
+ #
17
+ # for Ts = 20 ms and tau = 60 ms.
18
+ #
19
+ # The number exp(-1/3) is transcendental, so it is not available as a finite exact
20
+ # decimal. But for engineering we do not need mystical access to the exact real.
21
+ # We only need a finite certificate with controlled error.
22
+ #
23
+ # Integer-first / decimal-first move:
24
+ # We store a certified xsd:decimal interval
25
+ #
26
+ # 0.7165313105 <= exp(-1/3) <= 0.7165313106
27
+ #
28
+ # and propagate an exact decimal error envelope. Because xsd:decimal is finite symbolic
29
+ # data (effectively an integer coefficient plus a base-10 scale), the whole certificate
30
+ # remains machine-checkable and reproducible.
31
+ #
32
+ # What is certified:
33
+ # * the interval is nonempty and contractive
34
+ # * the error envelope shrinks at every sample
35
+ # * from an initial error of 12.5, the loop is guaranteed inside ±0.5 by sample 10
36
+ # * with Ts = 0.020 s, that means guaranteed settling by 0.200 s
37
+ # =======================================================================================
38
+
39
+ @prefix : <http://example.org/decimal-servo#>.
40
+ @prefix math: <http://www.w3.org/2000/10/swap/math#>.
41
+ @prefix log: <http://www.w3.org/2000/10/swap/log#>.
42
+ @prefix xsd: <http://www.w3.org/2001/XMLSchema#>.
43
+
44
+ # ----------
45
+ # Parameters
46
+ # ----------
47
+
48
+ :servo a :SampledServoEnvelope;
49
+ :samplePeriod "0.020"^^xsd:decimal;
50
+ :timeConstant "0.060"^^xsd:decimal;
51
+ :exactPoleSymbol "exp(-1/3)";
52
+ :poleLower "0.7165313105"^^xsd:decimal;
53
+ :poleUpper "0.7165313106"^^xsd:decimal;
54
+ :initialAbsError "12.5"^^xsd:decimal;
55
+ :tolerance "0.5"^^xsd:decimal;
56
+ :maxStep 12.
57
+
58
+ # -----------------------------------------------------------------
59
+ # The decimal interval is a finite certificate for a transcendental
60
+ # -----------------------------------------------------------------
61
+
62
+ {
63
+ :servo :poleLower ?lo; :poleUpper ?hi.
64
+ ?lo math:lessThan ?hi.
65
+ ?hi math:lessThan 1.
66
+ ?lo math:greaterThan 0.
67
+ }
68
+ =>
69
+ {
70
+ :servo :poleCertificate :CertifiedDecimalInterval.
71
+ :servo :contractivePole true.
72
+ }.
73
+
74
+ # ----------------
75
+ # Initial envelope
76
+ # ----------------
77
+
78
+ {
79
+ :servo :initialAbsError ?e0.
80
+ }
81
+ =>
82
+ {
83
+ :servo :errorEnvelopeAt (0 ?e0 ?e0).
84
+ }.
85
+
86
+ # -----------------------------------
87
+ # Envelope propagation
88
+ # lower(k+1) = poleLower * lower(k)
89
+ # upper(k+1) = poleUpper * upper(k)
90
+ # -----------------------------------
91
+
92
+ {
93
+ :servo :maxStep ?max;
94
+ :poleLower ?aLo;
95
+ :poleUpper ?aHi.
96
+ :servo :errorEnvelopeAt (?k ?lo ?hi).
97
+ ?k math:lessThan ?max.
98
+ ( ?k 1 ) math:sum ?k1.
99
+ ( ?aLo ?lo ) math:product ?lo1.
100
+ ( ?aHi ?hi ) math:product ?hi1.
101
+ }
102
+ =>
103
+ {
104
+ :servo :errorEnvelopeAt (?k1 ?lo1 ?hi1).
105
+ }.
106
+
107
+ # -----------------------------
108
+ # The envelope shrinks strictly
109
+ # -----------------------------
110
+
111
+ {
112
+ :servo :errorEnvelopeAt (?k ?lo ?hi).
113
+ ( ?k 1 ) math:sum ?k1.
114
+ :servo :errorEnvelopeAt (?k1 ?lo1 ?hi1).
115
+ ?hi1 math:lessThan ?hi.
116
+ }
117
+ =>
118
+ {
119
+ :servo :strictContractionAt ?k.
120
+ }.
121
+
122
+ # --------------------------------
123
+ # Settlement in the tolerance band
124
+ # --------------------------------
125
+
126
+ {
127
+ :servo :errorEnvelopeAt (?k ?lo ?hi).
128
+ :servo :tolerance ?tol.
129
+ ?hi math:lessThan ?tol.
130
+ }
131
+ =>
132
+ {
133
+ :servo :settledCandidate ?k.
134
+ }.
135
+
136
+ {
137
+ :servo :settledCandidate ?k.
138
+ ?k math:greaterThan 0.
139
+ ( ?k 1 ) math:difference ?km1.
140
+ :servo :errorEnvelopeAt (?km1 ?prevLo ?prevHi).
141
+ :servo :tolerance ?tol.
142
+ ?prevHi math:notLessThan ?tol.
143
+ }
144
+ =>
145
+ {
146
+ :servo :firstSettledStep ?k.
147
+ }.
148
+
149
+ {
150
+ :servo :firstSettledStep ?k.
151
+ :servo :samplePeriod ?ts.
152
+ ( ?k ?ts ) math:product ?t.
153
+ }
154
+ =>
155
+ {
156
+ :servo :firstSettledTime ?t.
157
+ }.
158
+
159
+ # --------------------------------------------------------
160
+ # Readable engineering summary for the decimal certificate
161
+ # --------------------------------------------------------
162
+
163
+ {
164
+ :servo :firstSettledStep ?k;
165
+ :firstSettledTime ?t;
166
+ :tolerance ?tol;
167
+ :exactPoleSymbol ?sym;
168
+ :poleLower ?aLo;
169
+ :poleUpper ?aHi.
170
+ }
171
+ log:query
172
+ {
173
+ :result :summary (
174
+ "exact-pole" ?sym
175
+ "decimal-lower" ?aLo
176
+ "decimal-upper" ?aHi
177
+ "tolerance" ?tol
178
+ "first-settled-step" ?k
179
+ "first-settled-time-s" ?t
180
+ ).
181
+ }.
182
+
183
+ {
184
+ :servo :errorEnvelopeAt (?k ?lo ?hi).
185
+ }
186
+ log:query
187
+ {
188
+ :result :envelope (?k ?lo ?hi).
189
+ }.
190
+
191
+ {
192
+ :servo :strictContractionAt ?k.
193
+ }
194
+ log:query
195
+ {
196
+ :result :contractionAt ?k.
197
+ }.