Skip to main content

oxilean_std/range/
functions.rs

1//! Auto-generated module
2//!
3//! 🤖 Generated with [SplitRS](https://github.com/cool-japan/splitrs)
4
5use oxilean_kernel::{BinderInfo, Declaration, Environment, Expr, Level, Name};
6
7use super::types::{
8    FloatInterval, IntervalScheduler, KrawczykSolver, RangeMinSegTree, ScheduledJob,
9    ValidatedInterval,
10};
11
12/// Prop: `Sort 0`.
13#[allow(dead_code)]
14pub fn prop() -> Expr {
15    Expr::Sort(Level::zero())
16}
17/// Type 1: `Sort 1`.
18#[allow(dead_code)]
19pub fn type1() -> Expr {
20    Expr::Sort(Level::succ(Level::zero()))
21}
22/// Type 2: `Sort 2`.
23#[allow(dead_code)]
24pub fn type2() -> Expr {
25    Expr::Sort(Level::succ(Level::succ(Level::zero())))
26}
27/// Nat type constant.
28#[allow(dead_code)]
29pub fn nat_ty() -> Expr {
30    Expr::Const(Name::str("Nat"), vec![])
31}
32/// Bool type constant.
33#[allow(dead_code)]
34pub fn bool_ty() -> Expr {
35    Expr::Const(Name::str("Bool"), vec![])
36}
37/// Unit type constant.
38#[allow(dead_code)]
39pub fn unit_ty() -> Expr {
40    Expr::Const(Name::str("Unit"), vec![])
41}
42/// Range type constant.
43#[allow(dead_code)]
44pub fn range_ty() -> Expr {
45    Expr::Const(Name::str("Range"), vec![])
46}
47/// RangeIterator type constant.
48#[allow(dead_code)]
49pub fn range_iterator_ty() -> Expr {
50    Expr::Const(Name::str("RangeIterator"), vec![])
51}
52/// `List` applied to a type argument.
53#[allow(dead_code)]
54pub fn list_of(elem_ty: Expr) -> Expr {
55    app(Expr::Const(Name::str("List"), vec![]), elem_ty)
56}
57/// `Array` applied to a type argument.
58#[allow(dead_code)]
59pub fn array_of(elem_ty: Expr) -> Expr {
60    app(Expr::Const(Name::str("Array"), vec![]), elem_ty)
61}
62/// `Option` applied to a type argument.
63#[allow(dead_code)]
64pub fn option_of(elem_ty: Expr) -> Expr {
65    app(Expr::Const(Name::str("Option"), vec![]), elem_ty)
66}
67/// `Prod` applied to two type arguments.
68#[allow(dead_code)]
69pub fn prod_of(a: Expr, b: Expr) -> Expr {
70    app2(Expr::Const(Name::str("Prod"), vec![]), a, b)
71}
72/// `Monad` applied to a type constructor.
73#[allow(dead_code)]
74pub fn monad_of(m: Expr) -> Expr {
75    app(Expr::Const(Name::str("Monad"), vec![]), m)
76}
77/// `Iff` applied to two propositions.
78#[allow(dead_code)]
79pub fn iff(a: Expr, b: Expr) -> Expr {
80    app2(Expr::Const(Name::str("Iff"), vec![]), a, b)
81}
82/// Build a non-dependent arrow `A -> B`.
83#[allow(dead_code)]
84pub fn arrow(a: Expr, b: Expr) -> Expr {
85    Expr::Pi(
86        BinderInfo::Default,
87        Name::str("_"),
88        Box::new(a),
89        Box::new(b),
90    )
91}
92/// Function application `f a`.
93#[allow(dead_code)]
94pub fn app(f: Expr, a: Expr) -> Expr {
95    Expr::App(Box::new(f), Box::new(a))
96}
97/// Function application `f a b`.
98#[allow(dead_code)]
99pub fn app2(f: Expr, a: Expr, b: Expr) -> Expr {
100    app(app(f, a), b)
101}
102/// Function application `f a b c`.
103#[allow(dead_code)]
104pub fn app3(f: Expr, a: Expr, b: Expr, c: Expr) -> Expr {
105    app(app2(f, a, b), c)
106}
107/// Function application `f a b c d`.
108#[allow(dead_code)]
109pub fn app4(f: Expr, a: Expr, b: Expr, c: Expr, d: Expr) -> Expr {
110    app(app3(f, a, b, c), d)
111}
112/// An implicit Pi binder.
113#[allow(dead_code)]
114pub fn implicit_pi(name: &str, ty: Expr, body: Expr) -> Expr {
115    Expr::Pi(
116        BinderInfo::Implicit,
117        Name::str(name),
118        Box::new(ty),
119        Box::new(body),
120    )
121}
122/// A default (explicit) Pi binder.
123#[allow(dead_code)]
124pub fn default_pi(name: &str, ty: Expr, body: Expr) -> Expr {
125    Expr::Pi(
126        BinderInfo::Default,
127        Name::str(name),
128        Box::new(ty),
129        Box::new(body),
130    )
131}
132/// An instance-implicit Pi binder.
133#[allow(dead_code)]
134pub fn inst_pi(name: &str, ty: Expr, body: Expr) -> Expr {
135    Expr::Pi(
136        BinderInfo::InstImplicit,
137        Name::str(name),
138        Box::new(ty),
139        Box::new(body),
140    )
141}
142/// Build `Eq @{} ty a b`.
143#[allow(dead_code)]
144pub fn eq_expr(ty: Expr, a: Expr, b: Expr) -> Expr {
145    app3(Expr::Const(Name::str("Eq"), vec![]), ty, a, b)
146}
147/// Shorthand to add an axiom to env.
148#[allow(dead_code)]
149pub fn add_axiom(
150    env: &mut Environment,
151    name: &str,
152    univ_params: Vec<Name>,
153    ty: Expr,
154) -> Result<(), String> {
155    env.add(Declaration::Axiom {
156        name: Name::str(name),
157        univ_params,
158        ty,
159    })
160    .map_err(|e| e.to_string())
161}
162/// `Type → Type` (kind of a type constructor like a monad).
163#[allow(dead_code)]
164pub fn type_to_type() -> Expr {
165    arrow(type1(), type1())
166}
167/// Build `And a b`.
168#[allow(dead_code)]
169pub fn and_prop(a: Expr, b: Expr) -> Expr {
170    app2(Expr::Const(Name::str("And"), vec![]), a, b)
171}
172/// Build `Nat.le a b`.
173#[allow(dead_code)]
174pub fn le_nat(a: Expr, b: Expr) -> Expr {
175    app2(Expr::Const(Name::str("Nat.le"), vec![]), a, b)
176}
177/// Build `Nat.lt a b`.
178#[allow(dead_code)]
179pub fn lt_nat(a: Expr, b: Expr) -> Expr {
180    app2(Expr::Const(Name::str("Nat.lt"), vec![]), a, b)
181}
182/// Build `Nat.sub a b`.
183#[allow(dead_code)]
184pub fn sub_nat(a: Expr, b: Expr) -> Expr {
185    app2(Expr::Const(Name::str("Nat.sub"), vec![]), a, b)
186}
187/// Build `Nat.mod a b`.
188#[allow(dead_code)]
189pub fn mod_nat(a: Expr, b: Expr) -> Expr {
190    app2(Expr::Const(Name::str("Nat.mod"), vec![]), a, b)
191}
192/// Build `Nat.ge a b` (= Nat.le b a).
193#[allow(dead_code)]
194pub fn ge_nat(a: Expr, b: Expr) -> Expr {
195    le_nat(b, a)
196}
197/// Build `BEq.beq a b = Bool.true`.
198#[allow(dead_code)]
199pub fn eq_true(e: Expr) -> Expr {
200    eq_expr(bool_ty(), e, Expr::Const(Name::str("Bool.true"), vec![]))
201}
202/// Build the Range type, iteration protocols, operations, and theorems.
203///
204/// Assumes that `Nat`, `Bool`, `Unit`, `List`, `Array`, `Option`, `Prod`,
205/// `Monad`, `Eq`, `Iff`, `And` are already declared or referenced by name.
206pub fn build_range_env(env: &mut Environment) -> Result<(), String> {
207    add_axiom(env, "Range", vec![], type1())?;
208    let range_mk_ty = default_pi(
209        "start",
210        nat_ty(),
211        default_pi("stop", nat_ty(), default_pi("step", nat_ty(), range_ty())),
212    );
213    add_axiom(env, "Range.mk", vec![], range_mk_ty)?;
214    let range_start_ty = arrow(range_ty(), nat_ty());
215    add_axiom(env, "Range.start", vec![], range_start_ty)?;
216    let range_stop_ty = arrow(range_ty(), nat_ty());
217    add_axiom(env, "Range.stop", vec![], range_stop_ty)?;
218    let range_step_ty = arrow(range_ty(), nat_ty());
219    add_axiom(env, "Range.step", vec![], range_step_ty)?;
220    let of_nat_ty = default_pi("start", nat_ty(), default_pi("stop", nat_ty(), range_ty()));
221    add_axiom(env, "Range.ofNat", vec![], of_nat_ty)?;
222    let single_ty = arrow(nat_ty(), range_ty());
223    add_axiom(env, "Range.single", vec![], single_ty)?;
224    let with_step_ty = default_pi(
225        "start",
226        nat_ty(),
227        default_pi("stop", nat_ty(), default_pi("step", nat_ty(), range_ty())),
228    );
229    add_axiom(env, "Range.withStep", vec![], with_step_ty)?;
230    let for_in_ty = default_pi(
231        "m",
232        type_to_type(),
233        default_pi("α", type1(), default_pi("β", type1(), type2())),
234    );
235    add_axiom(env, "ForIn", vec![], for_in_ty)?;
236    let for_in_method_ty = implicit_pi(
237        "m",
238        type_to_type(),
239        implicit_pi(
240            "α",
241            type1(),
242            implicit_pi(
243                "β",
244                type1(),
245                inst_pi(
246                    "_inst",
247                    app3(
248                        Expr::Const(Name::str("ForIn"), vec![]),
249                        Expr::BVar(2),
250                        Expr::BVar(1),
251                        Expr::BVar(0),
252                    ),
253                    default_pi(
254                        "container",
255                        Expr::BVar(2),
256                        default_pi(
257                            "init",
258                            Expr::BVar(2),
259                            default_pi(
260                                "body",
261                                arrow(Expr::BVar(3), app(Expr::BVar(6), Expr::BVar(4))),
262                                app(Expr::BVar(6), Expr::BVar(4)),
263                            ),
264                        ),
265                    ),
266                ),
267            ),
268        ),
269    );
270    add_axiom(env, "ForIn.forIn", vec![], for_in_method_ty)?;
271    let inst_for_in_range_ty = app3(
272        Expr::Const(Name::str("ForIn"), vec![]),
273        Expr::Const(Name::str("Id"), vec![]),
274        range_ty(),
275        nat_ty(),
276    );
277    add_axiom(env, "instForInRangeNat", vec![], inst_for_in_range_ty)?;
278    let iterator_ty = default_pi("α", type1(), default_pi("σ", type1(), type2()));
279    add_axiom(env, "Iterator", vec![], iterator_ty)?;
280    let next_ty = implicit_pi(
281        "α",
282        type1(),
283        implicit_pi(
284            "σ",
285            type1(),
286            inst_pi(
287                "_inst",
288                app2(
289                    Expr::Const(Name::str("Iterator"), vec![]),
290                    Expr::BVar(1),
291                    Expr::BVar(0),
292                ),
293                default_pi(
294                    "state",
295                    Expr::BVar(1),
296                    option_of(prod_of(Expr::BVar(3), Expr::BVar(2))),
297                ),
298            ),
299        ),
300    );
301    add_axiom(env, "Iterator.next", vec![], next_ty)?;
302    let has_next_ty = implicit_pi(
303        "α",
304        type1(),
305        implicit_pi(
306            "σ",
307            type1(),
308            inst_pi(
309                "_inst",
310                app2(
311                    Expr::Const(Name::str("Iterator"), vec![]),
312                    Expr::BVar(1),
313                    Expr::BVar(0),
314                ),
315                default_pi("state", Expr::BVar(1), bool_ty()),
316            ),
317        ),
318    );
319    add_axiom(env, "Iterator.hasNext", vec![], has_next_ty)?;
320    add_axiom(env, "RangeIterator", vec![], type1())?;
321    let inst_iter_ty = app2(
322        Expr::Const(Name::str("Iterator"), vec![]),
323        nat_ty(),
324        range_iterator_ty(),
325    );
326    add_axiom(env, "instIteratorNatRangeIterator", vec![], inst_iter_ty)?;
327    let is_empty_ty = arrow(range_ty(), bool_ty());
328    add_axiom(env, "Range.isEmpty", vec![], is_empty_ty)?;
329    let size_ty = arrow(range_ty(), nat_ty());
330    add_axiom(env, "Range.size", vec![], size_ty)?;
331    let contains_ty = default_pi("r", range_ty(), default_pi("n", nat_ty(), bool_ty()));
332    add_axiom(env, "Range.contains", vec![], contains_ty)?;
333    let to_list_ty = arrow(range_ty(), list_of(nat_ty()));
334    add_axiom(env, "Range.toList", vec![], to_list_ty)?;
335    let for_m_ty = implicit_pi(
336        "m",
337        type_to_type(),
338        inst_pi(
339            "_inst",
340            monad_of(Expr::BVar(0)),
341            default_pi(
342                "r",
343                range_ty(),
344                default_pi(
345                    "body",
346                    arrow(nat_ty(), app(Expr::BVar(3), unit_ty())),
347                    app(Expr::BVar(3), unit_ty()),
348                ),
349            ),
350        ),
351    );
352    add_axiom(env, "Range.forM", vec![], for_m_ty)?;
353    let foldl_ty = implicit_pi(
354        "β",
355        type1(),
356        default_pi(
357            "f",
358            arrow(Expr::BVar(0), arrow(nat_ty(), Expr::BVar(1))),
359            default_pi(
360                "init",
361                Expr::BVar(1),
362                default_pi("r", range_ty(), Expr::BVar(3)),
363            ),
364        ),
365    );
366    add_axiom(env, "Range.foldl", vec![], foldl_ty)?;
367    let all_ty = default_pi(
368        "r",
369        range_ty(),
370        default_pi("pred", arrow(nat_ty(), bool_ty()), bool_ty()),
371    );
372    add_axiom(env, "Range.all", vec![], all_ty)?;
373    let any_ty = default_pi(
374        "r",
375        range_ty(),
376        default_pi("pred", arrow(nat_ty(), bool_ty()), bool_ty()),
377    );
378    add_axiom(env, "Range.any", vec![], any_ty)?;
379    let array_range_ty = arrow(nat_ty(), array_of(nat_ty()));
380    add_axiom(env, "Array.range", vec![], array_range_ty)?;
381    let list_range_ty = arrow(nat_ty(), list_of(nat_ty()));
382    add_axiom(env, "List.range", vec![], list_range_ty)?;
383    let list_iota_ty = arrow(nat_ty(), list_of(nat_ty()));
384    add_axiom(env, "List.iota", vec![], list_iota_ty)?;
385    let enum_from_ty = implicit_pi(
386        "α",
387        type1(),
388        default_pi(
389            "start",
390            nat_ty(),
391            default_pi(
392                "l",
393                list_of(Expr::BVar(1)),
394                list_of(prod_of(nat_ty(), Expr::BVar(2))),
395            ),
396        ),
397    );
398    add_axiom(env, "List.enumFrom", vec![], enum_from_ty)?;
399    let size_mk_ty = default_pi(
400        "start",
401        nat_ty(),
402        default_pi(
403            "stop",
404            nat_ty(),
405            eq_expr(
406                nat_ty(),
407                app(
408                    Expr::Const(Name::str("Range.size"), vec![]),
409                    app3(
410                        Expr::Const(Name::str("Range.mk"), vec![]),
411                        Expr::BVar(1),
412                        Expr::BVar(0),
413                        Expr::Const(Name::str("Nat.one"), vec![]),
414                    ),
415                ),
416                sub_nat(Expr::BVar(0), Expr::BVar(1)),
417            ),
418        ),
419    );
420    add_axiom(env, "Range.size_mk", vec![], size_mk_ty)?;
421    let contains_iff_ty = default_pi(
422        "start",
423        nat_ty(),
424        default_pi(
425            "stop",
426            nat_ty(),
427            default_pi(
428                "step",
429                nat_ty(),
430                default_pi(
431                    "n",
432                    nat_ty(),
433                    iff(
434                        eq_true(app2(
435                            Expr::Const(Name::str("Range.contains"), vec![]),
436                            app3(
437                                Expr::Const(Name::str("Range.mk"), vec![]),
438                                Expr::BVar(3),
439                                Expr::BVar(2),
440                                Expr::BVar(1),
441                            ),
442                            Expr::BVar(0),
443                        )),
444                        and_prop(
445                            le_nat(Expr::BVar(3), Expr::BVar(0)),
446                            and_prop(
447                                lt_nat(Expr::BVar(0), Expr::BVar(2)),
448                                eq_expr(
449                                    nat_ty(),
450                                    mod_nat(sub_nat(Expr::BVar(0), Expr::BVar(3)), Expr::BVar(1)),
451                                    Expr::Const(Name::str("Nat.zero"), vec![]),
452                                ),
453                            ),
454                        ),
455                    ),
456                ),
457            ),
458        ),
459    );
460    add_axiom(env, "Range.contains_iff", vec![], contains_iff_ty)?;
461    let to_list_length_ty = default_pi(
462        "r",
463        range_ty(),
464        eq_expr(
465            nat_ty(),
466            app(
467                Expr::Const(Name::str("List.length"), vec![]),
468                app(
469                    Expr::Const(Name::str("Range.toList"), vec![]),
470                    Expr::BVar(0),
471                ),
472            ),
473            app(Expr::Const(Name::str("Range.size"), vec![]), Expr::BVar(0)),
474        ),
475    );
476    add_axiom(env, "Range.toList_length", vec![], to_list_length_ty)?;
477    let is_empty_iff_ty = default_pi(
478        "r",
479        range_ty(),
480        iff(
481            eq_true(app(
482                Expr::Const(Name::str("Range.isEmpty"), vec![]),
483                Expr::BVar(0),
484            )),
485            ge_nat(
486                app(Expr::Const(Name::str("Range.start"), vec![]), Expr::BVar(0)),
487                app(Expr::Const(Name::str("Range.stop"), vec![]), Expr::BVar(0)),
488            ),
489        ),
490    );
491    add_axiom(env, "Range.isEmpty_iff", vec![], is_empty_iff_ty)?;
492    let range_length_ty = default_pi(
493        "n",
494        nat_ty(),
495        eq_expr(
496            nat_ty(),
497            app(
498                Expr::Const(Name::str("List.length"), vec![]),
499                app(Expr::Const(Name::str("List.range"), vec![]), Expr::BVar(0)),
500            ),
501            Expr::BVar(0),
502        ),
503    );
504    add_axiom(env, "List.range_length", vec![], range_length_ty)?;
505    let iota_length_ty = default_pi(
506        "n",
507        nat_ty(),
508        eq_expr(
509            nat_ty(),
510            app(
511                Expr::Const(Name::str("List.length"), vec![]),
512                app(Expr::Const(Name::str("List.iota"), vec![]), Expr::BVar(0)),
513            ),
514            Expr::BVar(0),
515        ),
516    );
517    add_axiom(env, "List.iota_length", vec![], iota_length_ty)?;
518    Ok(())
519}
520/// Build `Range.mk start stop step`.
521#[allow(dead_code)]
522pub fn mk_range(start: Expr, stop: Expr, step: Expr) -> Expr {
523    app3(
524        Expr::Const(Name::str("Range.mk"), vec![]),
525        start,
526        stop,
527        step,
528    )
529}
530/// Build `Range.ofNat start stop`.
531#[allow(dead_code)]
532pub fn mk_range_of_nat(start: Expr, stop: Expr) -> Expr {
533    app2(Expr::Const(Name::str("Range.ofNat"), vec![]), start, stop)
534}
535/// Build `Range.single n`.
536#[allow(dead_code)]
537pub fn mk_range_single(n: Expr) -> Expr {
538    app(Expr::Const(Name::str("Range.single"), vec![]), n)
539}
540/// Build `ForIn.forIn container init body`.
541#[allow(dead_code)]
542pub fn mk_for_in(container: Expr, init: Expr, body: Expr) -> Expr {
543    app3(
544        Expr::Const(Name::str("ForIn.forIn"), vec![]),
545        container,
546        init,
547        body,
548    )
549}
550/// Build `Range.toList r`.
551#[allow(dead_code)]
552pub fn mk_range_to_list(r: Expr) -> Expr {
553    app(Expr::Const(Name::str("Range.toList"), vec![]), r)
554}
555/// Build `Range.size r`.
556#[allow(dead_code)]
557pub fn mk_range_size(r: Expr) -> Expr {
558    app(Expr::Const(Name::str("Range.size"), vec![]), r)
559}
560/// Build `List.range n`.
561#[allow(dead_code)]
562pub fn mk_list_range(n: Expr) -> Expr {
563    app(Expr::Const(Name::str("List.range"), vec![]), n)
564}
565/// Build `Array.range n`.
566#[allow(dead_code)]
567pub fn mk_array_range(n: Expr) -> Expr {
568    app(Expr::Const(Name::str("Array.range"), vec![]), n)
569}
570/// Build `List.iota n`.
571#[allow(dead_code)]
572pub fn mk_list_iota(n: Expr) -> Expr {
573    app(Expr::Const(Name::str("List.iota"), vec![]), n)
574}
575/// Build `Range.isEmpty r`.
576#[allow(dead_code)]
577pub fn mk_range_is_empty(r: Expr) -> Expr {
578    app(Expr::Const(Name::str("Range.isEmpty"), vec![]), r)
579}
580/// Build `Range.contains r n`.
581#[allow(dead_code)]
582pub fn mk_range_contains(r: Expr, n: Expr) -> Expr {
583    app2(Expr::Const(Name::str("Range.contains"), vec![]), r, n)
584}
585/// Build `Range.foldl f init r`.
586#[allow(dead_code)]
587pub fn mk_range_foldl(f: Expr, init: Expr, r: Expr) -> Expr {
588    app3(Expr::Const(Name::str("Range.foldl"), vec![]), f, init, r)
589}
590/// Build `Range.all r pred`.
591#[allow(dead_code)]
592pub fn mk_range_all(r: Expr, pred: Expr) -> Expr {
593    app2(Expr::Const(Name::str("Range.all"), vec![]), r, pred)
594}
595/// Build `Range.any r pred`.
596#[allow(dead_code)]
597pub fn mk_range_any(r: Expr, pred: Expr) -> Expr {
598    app2(Expr::Const(Name::str("Range.any"), vec![]), r, pred)
599}
600/// Build `Range.start r`.
601#[allow(dead_code)]
602pub fn mk_range_start(r: Expr) -> Expr {
603    app(Expr::Const(Name::str("Range.start"), vec![]), r)
604}
605/// Build `Range.stop r`.
606#[allow(dead_code)]
607pub fn mk_range_stop(r: Expr) -> Expr {
608    app(Expr::Const(Name::str("Range.stop"), vec![]), r)
609}
610/// Build `Range.step r`.
611#[allow(dead_code)]
612pub fn mk_range_step(r: Expr) -> Expr {
613    app(Expr::Const(Name::str("Range.step"), vec![]), r)
614}
615/// Build `Range.withStep start stop step`.
616#[allow(dead_code)]
617pub fn mk_range_with_step(start: Expr, stop: Expr, step: Expr) -> Expr {
618    app3(
619        Expr::Const(Name::str("Range.withStep"), vec![]),
620        start,
621        stop,
622        step,
623    )
624}
625/// Build `List.enumFrom start l`.
626#[allow(dead_code)]
627pub fn mk_list_enum_from(start: Expr, l: Expr) -> Expr {
628    app2(Expr::Const(Name::str("List.enumFrom"), vec![]), start, l)
629}
630/// Build `Range.forM r body`.
631#[allow(dead_code)]
632pub fn mk_range_for_m(r: Expr, body: Expr) -> Expr {
633    app2(Expr::Const(Name::str("Range.forM"), vec![]), r, body)
634}
635/// Build `Iterator.next state`.
636#[allow(dead_code)]
637pub fn mk_iterator_next(state: Expr) -> Expr {
638    app(Expr::Const(Name::str("Iterator.next"), vec![]), state)
639}
640/// Build `Iterator.hasNext state`.
641#[allow(dead_code)]
642pub fn mk_iterator_has_next(state: Expr) -> Expr {
643    app(Expr::Const(Name::str("Iterator.hasNext"), vec![]), state)
644}
645#[cfg(test)]
646mod tests {
647    use super::*;
648    fn make_env() -> Environment {
649        let mut env = Environment::new();
650        build_range_env(&mut env).expect("build_range_env should succeed");
651        env
652    }
653    #[test]
654    fn test_build_range_env_succeeds() {
655        let mut env = Environment::new();
656        assert!(build_range_env(&mut env).is_ok());
657    }
658    #[test]
659    fn test_range_type_exists() {
660        let env = make_env();
661        assert!(env.get(&Name::str("Range")).is_some());
662    }
663    #[test]
664    fn test_range_mk_exists() {
665        let env = make_env();
666        assert!(env.get(&Name::str("Range.mk")).is_some());
667    }
668    #[test]
669    fn test_range_start_exists() {
670        let env = make_env();
671        assert!(env.get(&Name::str("Range.start")).is_some());
672    }
673    #[test]
674    fn test_range_stop_exists() {
675        let env = make_env();
676        assert!(env.get(&Name::str("Range.stop")).is_some());
677    }
678    #[test]
679    fn test_range_step_exists() {
680        let env = make_env();
681        assert!(env.get(&Name::str("Range.step")).is_some());
682    }
683    #[test]
684    fn test_range_of_nat_exists() {
685        let env = make_env();
686        assert!(env.get(&Name::str("Range.ofNat")).is_some());
687    }
688    #[test]
689    fn test_range_single_exists() {
690        let env = make_env();
691        assert!(env.get(&Name::str("Range.single")).is_some());
692    }
693    #[test]
694    fn test_range_with_step_exists() {
695        let env = make_env();
696        assert!(env.get(&Name::str("Range.withStep")).is_some());
697    }
698    #[test]
699    fn test_for_in_exists() {
700        let env = make_env();
701        assert!(env.get(&Name::str("ForIn")).is_some());
702    }
703    #[test]
704    fn test_for_in_method_exists() {
705        let env = make_env();
706        assert!(env.get(&Name::str("ForIn.forIn")).is_some());
707    }
708    #[test]
709    fn test_inst_for_in_range_nat_exists() {
710        let env = make_env();
711        assert!(env.get(&Name::str("instForInRangeNat")).is_some());
712    }
713    #[test]
714    fn test_iterator_exists() {
715        let env = make_env();
716        assert!(env.get(&Name::str("Iterator")).is_some());
717    }
718    #[test]
719    fn test_iterator_next_exists() {
720        let env = make_env();
721        assert!(env.get(&Name::str("Iterator.next")).is_some());
722    }
723    #[test]
724    fn test_iterator_has_next_exists() {
725        let env = make_env();
726        assert!(env.get(&Name::str("Iterator.hasNext")).is_some());
727    }
728    #[test]
729    fn test_range_iterator_exists() {
730        let env = make_env();
731        assert!(env.get(&Name::str("RangeIterator")).is_some());
732    }
733    #[test]
734    fn test_inst_iterator_nat_range_exists() {
735        let env = make_env();
736        assert!(env
737            .get(&Name::str("instIteratorNatRangeIterator"))
738            .is_some());
739    }
740    #[test]
741    fn test_range_is_empty_exists() {
742        let env = make_env();
743        assert!(env.get(&Name::str("Range.isEmpty")).is_some());
744    }
745    #[test]
746    fn test_range_size_exists() {
747        let env = make_env();
748        assert!(env.get(&Name::str("Range.size")).is_some());
749    }
750    #[test]
751    fn test_range_contains_exists() {
752        let env = make_env();
753        assert!(env.get(&Name::str("Range.contains")).is_some());
754    }
755    #[test]
756    fn test_range_to_list_exists() {
757        let env = make_env();
758        assert!(env.get(&Name::str("Range.toList")).is_some());
759    }
760    #[test]
761    fn test_range_for_m_exists() {
762        let env = make_env();
763        assert!(env.get(&Name::str("Range.forM")).is_some());
764    }
765    #[test]
766    fn test_range_foldl_exists() {
767        let env = make_env();
768        assert!(env.get(&Name::str("Range.foldl")).is_some());
769    }
770    #[test]
771    fn test_range_all_exists() {
772        let env = make_env();
773        assert!(env.get(&Name::str("Range.all")).is_some());
774    }
775    #[test]
776    fn test_range_any_exists() {
777        let env = make_env();
778        assert!(env.get(&Name::str("Range.any")).is_some());
779    }
780    #[test]
781    fn test_array_range_exists() {
782        let env = make_env();
783        assert!(env.get(&Name::str("Array.range")).is_some());
784    }
785    #[test]
786    fn test_list_range_exists() {
787        let env = make_env();
788        assert!(env.get(&Name::str("List.range")).is_some());
789    }
790    #[test]
791    fn test_list_iota_exists() {
792        let env = make_env();
793        assert!(env.get(&Name::str("List.iota")).is_some());
794    }
795    #[test]
796    fn test_list_enum_from_exists() {
797        let env = make_env();
798        assert!(env.get(&Name::str("List.enumFrom")).is_some());
799    }
800    #[test]
801    fn test_range_size_mk_exists() {
802        let env = make_env();
803        assert!(env.get(&Name::str("Range.size_mk")).is_some());
804    }
805    #[test]
806    fn test_range_contains_iff_exists() {
807        let env = make_env();
808        assert!(env.get(&Name::str("Range.contains_iff")).is_some());
809    }
810    #[test]
811    fn test_range_to_list_length_exists() {
812        let env = make_env();
813        assert!(env.get(&Name::str("Range.toList_length")).is_some());
814    }
815    #[test]
816    fn test_range_is_empty_iff_exists() {
817        let env = make_env();
818        assert!(env.get(&Name::str("Range.isEmpty_iff")).is_some());
819    }
820    #[test]
821    fn test_list_range_length_exists() {
822        let env = make_env();
823        assert!(env.get(&Name::str("List.range_length")).is_some());
824    }
825    #[test]
826    fn test_list_iota_length_exists() {
827        let env = make_env();
828        assert!(env.get(&Name::str("List.iota_length")).is_some());
829    }
830    #[test]
831    fn test_mk_range() {
832        let r = mk_range(
833            Expr::Const(Name::str("a"), vec![]),
834            Expr::Const(Name::str("b"), vec![]),
835            Expr::Const(Name::str("c"), vec![]),
836        );
837        assert!(matches!(r, Expr::App(_, _)));
838    }
839    #[test]
840    fn test_mk_range_of_nat() {
841        let r = mk_range_of_nat(
842            Expr::Const(Name::str("a"), vec![]),
843            Expr::Const(Name::str("b"), vec![]),
844        );
845        assert!(matches!(r, Expr::App(_, _)));
846    }
847    #[test]
848    fn test_mk_range_single() {
849        let r = mk_range_single(Expr::Const(Name::str("n"), vec![]));
850        assert!(matches!(r, Expr::App(_, _)));
851    }
852    #[test]
853    fn test_mk_for_in() {
854        let f = mk_for_in(
855            Expr::Const(Name::str("c"), vec![]),
856            Expr::Const(Name::str("i"), vec![]),
857            Expr::Const(Name::str("b"), vec![]),
858        );
859        assert!(matches!(f, Expr::App(_, _)));
860    }
861    #[test]
862    fn test_mk_range_to_list() {
863        let l = mk_range_to_list(Expr::Const(Name::str("r"), vec![]));
864        assert!(matches!(l, Expr::App(_, _)));
865    }
866    #[test]
867    fn test_mk_range_size() {
868        let s = mk_range_size(Expr::Const(Name::str("r"), vec![]));
869        assert!(matches!(s, Expr::App(_, _)));
870    }
871    #[test]
872    fn test_mk_list_range() {
873        let l = mk_list_range(Expr::Const(Name::str("n"), vec![]));
874        assert!(matches!(l, Expr::App(_, _)));
875    }
876    #[test]
877    fn test_all_declarations_are_axioms() {
878        let env = make_env();
879        for name in [
880            "Range",
881            "Range.mk",
882            "Range.start",
883            "Range.stop",
884            "Range.step",
885            "Range.ofNat",
886            "Range.single",
887            "Range.withStep",
888            "ForIn",
889            "ForIn.forIn",
890            "instForInRangeNat",
891            "Iterator",
892            "Iterator.next",
893            "Iterator.hasNext",
894            "RangeIterator",
895            "instIteratorNatRangeIterator",
896            "Range.isEmpty",
897            "Range.size",
898            "Range.contains",
899            "Range.toList",
900            "Range.forM",
901            "Range.foldl",
902            "Range.all",
903            "Range.any",
904            "Array.range",
905            "List.range",
906            "List.iota",
907            "List.enumFrom",
908        ] {
909            let decl = env.get(&Name::str(name)).expect("operation should succeed");
910            assert!(
911                matches!(decl, Declaration::Axiom { .. }),
912                "{} should be an axiom",
913                name
914            );
915        }
916    }
917    #[test]
918    fn test_env_declaration_count() {
919        let env = make_env();
920        assert!(env.len() >= 30);
921    }
922    #[test]
923    fn test_range_mk_type_is_pi() {
924        let env = make_env();
925        let decl = env
926            .get(&Name::str("Range.mk"))
927            .expect("declaration 'Range.mk' should exist in env");
928        assert!(decl.ty().is_pi());
929    }
930    #[test]
931    fn test_range_foldl_type_is_pi() {
932        let env = make_env();
933        let decl = env
934            .get(&Name::str("Range.foldl"))
935            .expect("declaration 'Range.foldl' should exist in env");
936        assert!(decl.ty().is_pi());
937    }
938    #[test]
939    fn test_range_type_is_sort() {
940        let env = make_env();
941        let decl = env
942            .get(&Name::str("Range"))
943            .expect("declaration 'Range' should exist in env");
944        assert!(decl.ty().is_sort());
945    }
946    #[test]
947    fn test_range_iterator_type_is_sort() {
948        let env = make_env();
949        let decl = env
950            .get(&Name::str("RangeIterator"))
951            .expect("declaration 'RangeIterator' should exist in env");
952        assert!(decl.ty().is_sort());
953    }
954}
955pub fn rng_ext_type1() -> Expr {
956    Expr::Sort(Level::succ(Level::zero()))
957}
958pub fn rng_ext_type2() -> Expr {
959    Expr::Sort(Level::succ(Level::succ(Level::zero())))
960}
961pub fn rng_ext_prop() -> Expr {
962    Expr::Sort(Level::zero())
963}
964pub fn rng_ext_arrow(dom: Expr, cod: Expr) -> Expr {
965    Expr::Pi(
966        BinderInfo::Default,
967        Name::str("_"),
968        Box::new(dom),
969        Box::new(cod),
970    )
971}
972pub fn rng_ext_pi(name: &str, dom: Expr, body: Expr) -> Expr {
973    Expr::Pi(
974        BinderInfo::Default,
975        Name::str(name),
976        Box::new(dom),
977        Box::new(body),
978    )
979}
980pub fn rng_ext_ipi(name: &str, dom: Expr, body: Expr) -> Expr {
981    Expr::Pi(
982        BinderInfo::Implicit,
983        Name::str(name),
984        Box::new(dom),
985        Box::new(body),
986    )
987}
988pub fn rng_ext_app(f: Expr, a: Expr) -> Expr {
989    Expr::App(Box::new(f), Box::new(a))
990}
991pub fn rng_ext_app2(f: Expr, a: Expr, b: Expr) -> Expr {
992    rng_ext_app(rng_ext_app(f, a), b)
993}
994pub fn rng_ext_app3(f: Expr, a: Expr, b: Expr, c: Expr) -> Expr {
995    rng_ext_app(rng_ext_app2(f, a, b), c)
996}
997pub fn rng_ext_nat() -> Expr {
998    Expr::Const(Name::str("Nat"), vec![])
999}
1000pub fn rng_ext_float() -> Expr {
1001    Expr::Const(Name::str("Float"), vec![])
1002}
1003pub fn rng_ext_bool() -> Expr {
1004    Expr::Const(Name::str("Bool"), vec![])
1005}
1006pub fn rng_ext_interval() -> Expr {
1007    Expr::Const(Name::str("Interval"), vec![])
1008}
1009pub fn rng_ext_interval_of(ty: Expr) -> Expr {
1010    rng_ext_app(Expr::Const(Name::str("Interval"), vec![]), ty)
1011}
1012pub fn rng_ext_eq(ty: Expr, a: Expr, b: Expr) -> Expr {
1013    rng_ext_app3(Expr::Const(Name::str("Eq"), vec![]), ty, a, b)
1014}
1015pub fn rng_ext_and(a: Expr, b: Expr) -> Expr {
1016    rng_ext_app2(Expr::Const(Name::str("And"), vec![]), a, b)
1017}
1018pub fn rng_ext_iff(a: Expr, b: Expr) -> Expr {
1019    rng_ext_app2(Expr::Const(Name::str("Iff"), vec![]), a, b)
1020}
1021pub fn rng_ext_le(a: Expr, b: Expr) -> Expr {
1022    rng_ext_app2(Expr::Const(Name::str("LE.le"), vec![]), a, b)
1023}
1024pub fn rng_ext_lt(a: Expr, b: Expr) -> Expr {
1025    rng_ext_app2(Expr::Const(Name::str("LT.lt"), vec![]), a, b)
1026}
1027pub fn rng_ext_add_axiom(env: &mut Environment, name: &str, ty: Expr) -> Result<(), String> {
1028    env.add(Declaration::Axiom {
1029        name: Name::str(name),
1030        univ_params: vec![],
1031        ty,
1032    })
1033    .map_err(|e| e.to_string())
1034}
1035/// `Interval : Type → Type` — a closed interval type parameterized by a numeric type.
1036pub fn axiom_interval_type_ty() -> Expr {
1037    rng_ext_arrow(rng_ext_type1(), rng_ext_type1())
1038}
1039/// `Interval.mk : {α : Type} → α → α → Interval α` — construct from lo and hi.
1040pub fn axiom_interval_mk_ty() -> Expr {
1041    rng_ext_ipi(
1042        "α",
1043        rng_ext_type1(),
1044        rng_ext_pi(
1045            "lo",
1046            Expr::BVar(0),
1047            rng_ext_pi("hi", Expr::BVar(1), rng_ext_interval_of(Expr::BVar(2))),
1048        ),
1049    )
1050}
1051/// `Interval.lo : {α : Type} → Interval α → α`.
1052pub fn axiom_interval_lo_ty() -> Expr {
1053    rng_ext_ipi(
1054        "α",
1055        rng_ext_type1(),
1056        rng_ext_arrow(rng_ext_interval_of(Expr::BVar(0)), Expr::BVar(0)),
1057    )
1058}
1059/// `Interval.hi : {α : Type} → Interval α → α`.
1060pub fn axiom_interval_hi_ty() -> Expr {
1061    rng_ext_ipi(
1062        "α",
1063        rng_ext_type1(),
1064        rng_ext_arrow(rng_ext_interval_of(Expr::BVar(0)), Expr::BVar(0)),
1065    )
1066}
1067/// `Interval.valid : {α : Type} → [Ord α] → Interval α → Prop` — lo ≤ hi.
1068pub fn axiom_interval_valid_ty() -> Expr {
1069    rng_ext_ipi(
1070        "α",
1071        rng_ext_type1(),
1072        Expr::Pi(
1073            BinderInfo::InstImplicit,
1074            Name::str("_"),
1075            Box::new(rng_ext_app(
1076                Expr::Const(Name::str("Ord"), vec![]),
1077                Expr::BVar(0),
1078            )),
1079            Box::new(rng_ext_arrow(
1080                rng_ext_interval_of(Expr::BVar(1)),
1081                rng_ext_prop(),
1082            )),
1083        ),
1084    )
1085}
1086/// `Interval.contains : {α : Type} → [Ord α] → Interval α → α → Prop`.
1087pub fn axiom_interval_contains_ty() -> Expr {
1088    rng_ext_ipi(
1089        "α",
1090        rng_ext_type1(),
1091        Expr::Pi(
1092            BinderInfo::InstImplicit,
1093            Name::str("_"),
1094            Box::new(rng_ext_app(
1095                Expr::Const(Name::str("Ord"), vec![]),
1096                Expr::BVar(0),
1097            )),
1098            Box::new(rng_ext_pi(
1099                "iv",
1100                rng_ext_interval_of(Expr::BVar(1)),
1101                rng_ext_pi("x", Expr::BVar(2), rng_ext_prop()),
1102            )),
1103        ),
1104    )
1105}
1106/// `Interval.add : Interval Float → Interval Float → Interval Float` — Moore addition.
1107pub fn axiom_interval_add_ty() -> Expr {
1108    rng_ext_arrow(
1109        rng_ext_interval_of(rng_ext_float()),
1110        rng_ext_arrow(
1111            rng_ext_interval_of(rng_ext_float()),
1112            rng_ext_interval_of(rng_ext_float()),
1113        ),
1114    )
1115}
1116/// `Interval.sub : Interval Float → Interval Float → Interval Float` — Moore subtraction.
1117pub fn axiom_interval_sub_ty() -> Expr {
1118    rng_ext_arrow(
1119        rng_ext_interval_of(rng_ext_float()),
1120        rng_ext_arrow(
1121            rng_ext_interval_of(rng_ext_float()),
1122            rng_ext_interval_of(rng_ext_float()),
1123        ),
1124    )
1125}
1126/// `Interval.mul : Interval Float → Interval Float → Interval Float` — Moore multiplication.
1127pub fn axiom_interval_mul_ty() -> Expr {
1128    rng_ext_arrow(
1129        rng_ext_interval_of(rng_ext_float()),
1130        rng_ext_arrow(
1131            rng_ext_interval_of(rng_ext_float()),
1132            rng_ext_interval_of(rng_ext_float()),
1133        ),
1134    )
1135}
1136/// `Interval.div : Interval Float → Interval Float → Interval Float` — Moore division (partial).
1137pub fn axiom_interval_div_ty() -> Expr {
1138    rng_ext_arrow(
1139        rng_ext_interval_of(rng_ext_float()),
1140        rng_ext_arrow(
1141            rng_ext_interval_of(rng_ext_float()),
1142            rng_ext_interval_of(rng_ext_float()),
1143        ),
1144    )
1145}
1146/// `Interval.width : Interval Float → Float` — hi - lo.
1147pub fn axiom_interval_width_ty() -> Expr {
1148    rng_ext_arrow(rng_ext_interval_of(rng_ext_float()), rng_ext_float())
1149}
1150/// `Interval.midpoint : Interval Float → Float` — (lo + hi) / 2.
1151pub fn axiom_interval_midpoint_ty() -> Expr {
1152    rng_ext_arrow(rng_ext_interval_of(rng_ext_float()), rng_ext_float())
1153}
1154/// `Interval.intersect : Interval Float → Interval Float → Option (Interval Float)`.
1155pub fn axiom_interval_intersect_ty() -> Expr {
1156    rng_ext_arrow(
1157        rng_ext_interval_of(rng_ext_float()),
1158        rng_ext_arrow(
1159            rng_ext_interval_of(rng_ext_float()),
1160            rng_ext_app(
1161                Expr::Const(Name::str("Option"), vec![]),
1162                rng_ext_interval_of(rng_ext_float()),
1163            ),
1164        ),
1165    )
1166}
1167/// `Interval.hull : Interval Float → Interval Float → Interval Float` — smallest enclosing interval.
1168pub fn axiom_interval_hull_ty() -> Expr {
1169    rng_ext_arrow(
1170        rng_ext_interval_of(rng_ext_float()),
1171        rng_ext_arrow(
1172            rng_ext_interval_of(rng_ext_float()),
1173            rng_ext_interval_of(rng_ext_float()),
1174        ),
1175    )
1176}
1177/// `Interval.subset : Interval Float → Interval Float → Prop`.
1178pub fn axiom_interval_subset_ty() -> Expr {
1179    rng_ext_arrow(
1180        rng_ext_interval_of(rng_ext_float()),
1181        rng_ext_arrow(rng_ext_interval_of(rng_ext_float()), rng_ext_prop()),
1182    )
1183}
1184/// `MooreArithmetic.inclusion_monotone : Prop` — inclusion monotonicity of Moore arithmetic.
1185pub fn axiom_moore_inclusion_monotone_ty() -> Expr {
1186    rng_ext_prop()
1187}
1188/// `MooreArithmetic.fundamental_theorem : Prop` — fundamental theorem of interval arithmetic.
1189pub fn axiom_moore_fundamental_theorem_ty() -> Expr {
1190    rng_ext_prop()
1191}
1192/// `IntervalNewton.step : (Float → Float) → Interval Float → Interval Float → Interval Float`.
1193pub fn axiom_interval_newton_step_ty() -> Expr {
1194    rng_ext_arrow(
1195        rng_ext_arrow(rng_ext_float(), rng_ext_float()),
1196        rng_ext_arrow(
1197            rng_ext_interval_of(rng_ext_float()),
1198            rng_ext_arrow(
1199                rng_ext_interval_of(rng_ext_float()),
1200                rng_ext_interval_of(rng_ext_float()),
1201            ),
1202        ),
1203    )
1204}
1205/// `IntervalNewton.converges : Prop` — the interval Newton method converges quadratically.
1206pub fn axiom_interval_newton_converges_ty() -> Expr {
1207    rng_ext_prop()
1208}
1209/// `Krawczyk.operator : (Float → Float) → Interval Float → Interval Float`.
1210pub fn axiom_krawczyk_operator_ty() -> Expr {
1211    rng_ext_arrow(
1212        rng_ext_arrow(rng_ext_float(), rng_ext_float()),
1213        rng_ext_arrow(
1214            rng_ext_interval_of(rng_ext_float()),
1215            rng_ext_interval_of(rng_ext_float()),
1216        ),
1217    )
1218}
1219/// `Krawczyk.enclosure_theorem : Prop` — Krawczyk's theorem for root enclosure.
1220pub fn axiom_krawczyk_enclosure_ty() -> Expr {
1221    rng_ext_prop()
1222}
1223/// `GaussSeidel.interval_step : Nat → Interval Float → Interval Float`.
1224pub fn axiom_gauss_seidel_interval_step_ty() -> Expr {
1225    rng_ext_pi(
1226        "n",
1227        rng_ext_nat(),
1228        rng_ext_arrow(
1229            rng_ext_interval_of(rng_ext_float()),
1230            rng_ext_interval_of(rng_ext_float()),
1231        ),
1232    )
1233}
1234/// `ValidatedNumerics.enclosure : (Float → Float) → Interval Float → Prop`.
1235pub fn axiom_validated_numerics_enclosure_ty() -> Expr {
1236    rng_ext_arrow(
1237        rng_ext_arrow(rng_ext_float(), rng_ext_float()),
1238        rng_ext_arrow(rng_ext_interval_of(rng_ext_float()), rng_ext_prop()),
1239    )
1240}
1241/// `IntervalPresheaf : Type 2` — intervals as a presheaf on the reals.
1242pub fn axiom_interval_presheaf_ty() -> Expr {
1243    rng_ext_type2()
1244}
1245/// `IntervalValuedProbability : Type` — interval-valued probability measure.
1246pub fn axiom_interval_valued_probability_ty() -> Expr {
1247    rng_ext_type1()
1248}
1249/// `IntervalValuedProbability.measure : IntervalValuedProbability → Interval Float`.
1250pub fn axiom_ivp_measure_ty() -> Expr {
1251    rng_ext_arrow(
1252        Expr::Const(Name::str("IntervalValuedProbability"), vec![]),
1253        rng_ext_interval_of(rng_ext_float()),
1254    )
1255}
1256/// `ModalInterval : Type` — modal interval arithmetic (proper and improper intervals).
1257pub fn axiom_modal_interval_ty() -> Expr {
1258    rng_ext_type1()
1259}
1260/// `ModalInterval.dual : ModalInterval → ModalInterval` — dual of a modal interval.
1261pub fn axiom_modal_interval_dual_ty() -> Expr {
1262    rng_ext_arrow(
1263        Expr::Const(Name::str("ModalInterval"), vec![]),
1264        Expr::Const(Name::str("ModalInterval"), vec![]),
1265    )
1266}
1267/// `IntervalLinearSystem.solve : Nat → (Interval Float) → Option (Interval Float)`.
1268pub fn axiom_interval_linear_system_solve_ty() -> Expr {
1269    rng_ext_pi(
1270        "n",
1271        rng_ext_nat(),
1272        rng_ext_arrow(
1273            rng_ext_interval_of(rng_ext_float()),
1274            rng_ext_app(
1275                Expr::Const(Name::str("Option"), vec![]),
1276                rng_ext_interval_of(rng_ext_float()),
1277            ),
1278        ),
1279    )
1280}
1281/// `DempsterShafer.belief : DempsterShafer → Interval Float`.
1282pub fn axiom_dempster_shafer_belief_ty() -> Expr {
1283    rng_ext_arrow(
1284        Expr::Const(Name::str("DempsterShafer"), vec![]),
1285        rng_ext_interval_of(rng_ext_float()),
1286    )
1287}
1288/// `DempsterShafer.plausibility : DempsterShafer → Interval Float`.
1289pub fn axiom_dempster_shafer_plausibility_ty() -> Expr {
1290    rng_ext_arrow(
1291        Expr::Const(Name::str("DempsterShafer"), vec![]),
1292        rng_ext_interval_of(rng_ext_float()),
1293    )
1294}
1295/// `FuzzyInterval : Type` — fuzzy interval for soft membership.
1296pub fn axiom_fuzzy_interval_ty() -> Expr {
1297    rng_ext_type1()
1298}
1299/// `FuzzyInterval.alpha_cut : FuzzyInterval → Float → Interval Float`.
1300pub fn axiom_fuzzy_interval_alpha_cut_ty() -> Expr {
1301    rng_ext_arrow(
1302        Expr::Const(Name::str("FuzzyInterval"), vec![]),
1303        rng_ext_arrow(rng_ext_float(), rng_ext_interval_of(rng_ext_float())),
1304    )
1305}
1306/// `SegmentTree : Type → Nat → Type` — segment tree for interval range queries.
1307pub fn axiom_segment_tree_ty() -> Expr {
1308    rng_ext_arrow(
1309        rng_ext_type1(),
1310        rng_ext_arrow(rng_ext_nat(), rng_ext_type1()),
1311    )
1312}
1313/// `SegmentTree.query : {α : Type} → {n : Nat} → SegmentTree α n → Nat → Nat → α`.
1314pub fn axiom_segment_tree_query_ty() -> Expr {
1315    rng_ext_ipi(
1316        "α",
1317        rng_ext_type1(),
1318        rng_ext_ipi(
1319            "n",
1320            rng_ext_nat(),
1321            rng_ext_pi(
1322                "tree",
1323                rng_ext_app2(
1324                    Expr::Const(Name::str("SegmentTree"), vec![]),
1325                    Expr::BVar(1),
1326                    Expr::BVar(0),
1327                ),
1328                rng_ext_pi(
1329                    "l",
1330                    rng_ext_nat(),
1331                    rng_ext_pi("r", rng_ext_nat(), Expr::BVar(4)),
1332                ),
1333            ),
1334        ),
1335    )
1336}
1337/// `SegmentTree.update : {α : Type} → {n : Nat} → SegmentTree α n → Nat → α → SegmentTree α n`.
1338pub fn axiom_segment_tree_update_ty() -> Expr {
1339    rng_ext_ipi(
1340        "α",
1341        rng_ext_type1(),
1342        rng_ext_ipi(
1343            "n",
1344            rng_ext_nat(),
1345            rng_ext_pi(
1346                "tree",
1347                rng_ext_app2(
1348                    Expr::Const(Name::str("SegmentTree"), vec![]),
1349                    Expr::BVar(1),
1350                    Expr::BVar(0),
1351                ),
1352                rng_ext_pi(
1353                    "i",
1354                    rng_ext_nat(),
1355                    rng_ext_pi(
1356                        "val",
1357                        Expr::BVar(3),
1358                        rng_ext_app2(
1359                            Expr::Const(Name::str("SegmentTree"), vec![]),
1360                            Expr::BVar(4),
1361                            Expr::BVar(3),
1362                        ),
1363                    ),
1364                ),
1365            ),
1366        ),
1367    )
1368}
1369/// `IntervalScheduling.WeightedJob : Type` — weighted job for interval scheduling.
1370pub fn axiom_weighted_job_ty() -> Expr {
1371    rng_ext_type1()
1372}
1373/// `IntervalScheduling.optimalSchedule : List WeightedJob → List WeightedJob`.
1374pub fn axiom_interval_scheduling_optimal_ty() -> Expr {
1375    rng_ext_arrow(
1376        rng_ext_app(
1377            Expr::Const(Name::str("List"), vec![]),
1378            Expr::Const(Name::str("WeightedJob"), vec![]),
1379        ),
1380        rng_ext_app(
1381            Expr::Const(Name::str("List"), vec![]),
1382            Expr::Const(Name::str("WeightedJob"), vec![]),
1383        ),
1384    )
1385}
1386/// `IntervalScheduling.dpCorrect : Prop` — DP solution correctness for WIS.
1387pub fn axiom_interval_scheduling_dp_correct_ty() -> Expr {
1388    rng_ext_prop()
1389}
1390/// `Range.foldl_correct : Prop` — foldl over ranges is correct with respect to List.foldl.
1391pub fn axiom_range_foldl_correct_ty() -> Expr {
1392    rng_ext_prop()
1393}
1394/// `Range.all_iff : Prop` — `Range.all r p = true ↔ ∀ n ∈ r, p n = true`.
1395pub fn axiom_range_all_iff_ty() -> Expr {
1396    rng_ext_prop()
1397}
1398/// `Range.any_iff : Prop` — `Range.any r p = true ↔ ∃ n ∈ r, p n = true`.
1399pub fn axiom_range_any_iff_ty() -> Expr {
1400    rng_ext_prop()
1401}
1402/// `IntervalArithmetic.correctRounding : Prop` — interval operations round outward correctly.
1403pub fn axiom_interval_correct_rounding_ty() -> Expr {
1404    rng_ext_prop()
1405}
1406/// `IntervalArithmetic.subtraction_anticlosure : Prop` — subtraction may expand intervals.
1407pub fn axiom_interval_subtraction_anticlosure_ty() -> Expr {
1408    rng_ext_prop()
1409}
1410/// `Interval.pow : Interval Float → Nat → Interval Float`.
1411pub fn axiom_interval_pow_ty() -> Expr {
1412    rng_ext_pi(
1413        "iv",
1414        rng_ext_interval_of(rng_ext_float()),
1415        rng_ext_pi("n", rng_ext_nat(), rng_ext_interval_of(rng_ext_float())),
1416    )
1417}
1418/// `Interval.sqrt : Interval Float → Option (Interval Float)`.
1419pub fn axiom_interval_sqrt_ty() -> Expr {
1420    rng_ext_arrow(
1421        rng_ext_interval_of(rng_ext_float()),
1422        rng_ext_app(
1423            Expr::Const(Name::str("Option"), vec![]),
1424            rng_ext_interval_of(rng_ext_float()),
1425        ),
1426    )
1427}
1428/// `Interval.exp : Interval Float → Interval Float`.
1429pub fn axiom_interval_exp_ty() -> Expr {
1430    rng_ext_arrow(
1431        rng_ext_interval_of(rng_ext_float()),
1432        rng_ext_interval_of(rng_ext_float()),
1433    )
1434}
1435/// `Interval.log : Interval Float → Option (Interval Float)` — log on positive intervals.
1436pub fn axiom_interval_log_ty() -> Expr {
1437    rng_ext_arrow(
1438        rng_ext_interval_of(rng_ext_float()),
1439        rng_ext_app(
1440            Expr::Const(Name::str("Option"), vec![]),
1441            rng_ext_interval_of(rng_ext_float()),
1442        ),
1443    )
1444}
1445/// `Interval.sin : Interval Float → Interval Float`.
1446pub fn axiom_interval_sin_ty() -> Expr {
1447    rng_ext_arrow(
1448        rng_ext_interval_of(rng_ext_float()),
1449        rng_ext_interval_of(rng_ext_float()),
1450    )
1451}
1452/// `Interval.cos : Interval Float → Interval Float`.
1453pub fn axiom_interval_cos_ty() -> Expr {
1454    rng_ext_arrow(
1455        rng_ext_interval_of(rng_ext_float()),
1456        rng_ext_interval_of(rng_ext_float()),
1457    )
1458}
1459/// `Interval.abs : Interval Float → Interval Float`.
1460pub fn axiom_interval_abs_ty() -> Expr {
1461    rng_ext_arrow(
1462        rng_ext_interval_of(rng_ext_float()),
1463        rng_ext_interval_of(rng_ext_float()),
1464    )
1465}
1466/// `Interval.neg : Interval Float → Interval Float`.
1467pub fn axiom_interval_neg_ty() -> Expr {
1468    rng_ext_arrow(
1469        rng_ext_interval_of(rng_ext_float()),
1470        rng_ext_interval_of(rng_ext_float()),
1471    )
1472}
1473/// Register all extended Range/Interval axioms into the environment.
1474pub fn register_range_extended(env: &mut Environment) -> Result<(), String> {
1475    rng_ext_add_axiom(env, "Interval", axiom_interval_type_ty())?;
1476    rng_ext_add_axiom(env, "Interval.mk", axiom_interval_mk_ty())?;
1477    rng_ext_add_axiom(env, "Interval.lo", axiom_interval_lo_ty())?;
1478    rng_ext_add_axiom(env, "Interval.hi", axiom_interval_hi_ty())?;
1479    rng_ext_add_axiom(env, "Interval.valid", axiom_interval_valid_ty())?;
1480    rng_ext_add_axiom(env, "Interval.contains", axiom_interval_contains_ty())?;
1481    rng_ext_add_axiom(env, "Interval.add", axiom_interval_add_ty())?;
1482    rng_ext_add_axiom(env, "Interval.sub", axiom_interval_sub_ty())?;
1483    rng_ext_add_axiom(env, "Interval.mul", axiom_interval_mul_ty())?;
1484    rng_ext_add_axiom(env, "Interval.div", axiom_interval_div_ty())?;
1485    rng_ext_add_axiom(env, "Interval.width", axiom_interval_width_ty())?;
1486    rng_ext_add_axiom(env, "Interval.midpoint", axiom_interval_midpoint_ty())?;
1487    rng_ext_add_axiom(env, "Interval.intersect", axiom_interval_intersect_ty())?;
1488    rng_ext_add_axiom(env, "Interval.hull", axiom_interval_hull_ty())?;
1489    rng_ext_add_axiom(env, "Interval.subset", axiom_interval_subset_ty())?;
1490    rng_ext_add_axiom(
1491        env,
1492        "MooreArithmetic.inclusion_monotone",
1493        axiom_moore_inclusion_monotone_ty(),
1494    )?;
1495    rng_ext_add_axiom(
1496        env,
1497        "MooreArithmetic.fundamental_theorem",
1498        axiom_moore_fundamental_theorem_ty(),
1499    )?;
1500    rng_ext_add_axiom(env, "IntervalNewton.step", axiom_interval_newton_step_ty())?;
1501    rng_ext_add_axiom(
1502        env,
1503        "IntervalNewton.converges",
1504        axiom_interval_newton_converges_ty(),
1505    )?;
1506    rng_ext_add_axiom(env, "Krawczyk.operator", axiom_krawczyk_operator_ty())?;
1507    rng_ext_add_axiom(
1508        env,
1509        "Krawczyk.enclosure_theorem",
1510        axiom_krawczyk_enclosure_ty(),
1511    )?;
1512    rng_ext_add_axiom(
1513        env,
1514        "ValidatedNumerics.enclosure",
1515        axiom_validated_numerics_enclosure_ty(),
1516    )?;
1517    rng_ext_add_axiom(env, "IntervalPresheaf", axiom_interval_presheaf_ty())?;
1518    rng_ext_add_axiom(
1519        env,
1520        "IntervalValuedProbability",
1521        axiom_interval_valued_probability_ty(),
1522    )?;
1523    rng_ext_add_axiom(
1524        env,
1525        "IntervalValuedProbability.measure",
1526        axiom_ivp_measure_ty(),
1527    )?;
1528    rng_ext_add_axiom(env, "ModalInterval", axiom_modal_interval_ty())?;
1529    rng_ext_add_axiom(env, "ModalInterval.dual", axiom_modal_interval_dual_ty())?;
1530    rng_ext_add_axiom(env, "FuzzyInterval", axiom_fuzzy_interval_ty())?;
1531    rng_ext_add_axiom(
1532        env,
1533        "FuzzyInterval.alpha_cut",
1534        axiom_fuzzy_interval_alpha_cut_ty(),
1535    )?;
1536    rng_ext_add_axiom(env, "SegmentTree", axiom_segment_tree_ty())?;
1537    rng_ext_add_axiom(env, "WeightedJob", axiom_weighted_job_ty())?;
1538    rng_ext_add_axiom(
1539        env,
1540        "IntervalScheduling.dpCorrect",
1541        axiom_interval_scheduling_dp_correct_ty(),
1542    )?;
1543    rng_ext_add_axiom(env, "Range.foldl_correct", axiom_range_foldl_correct_ty())?;
1544    rng_ext_add_axiom(env, "Range.all_iff", axiom_range_all_iff_ty())?;
1545    rng_ext_add_axiom(env, "Range.any_iff", axiom_range_any_iff_ty())?;
1546    rng_ext_add_axiom(
1547        env,
1548        "IntervalArithmetic.correctRounding",
1549        axiom_interval_correct_rounding_ty(),
1550    )?;
1551    rng_ext_add_axiom(env, "Interval.pow", axiom_interval_pow_ty())?;
1552    rng_ext_add_axiom(env, "Interval.sqrt", axiom_interval_sqrt_ty())?;
1553    rng_ext_add_axiom(env, "Interval.exp", axiom_interval_exp_ty())?;
1554    rng_ext_add_axiom(env, "Interval.log", axiom_interval_log_ty())?;
1555    rng_ext_add_axiom(env, "Interval.sin", axiom_interval_sin_ty())?;
1556    rng_ext_add_axiom(env, "Interval.cos", axiom_interval_cos_ty())?;
1557    rng_ext_add_axiom(env, "Interval.abs", axiom_interval_abs_ty())?;
1558    rng_ext_add_axiom(env, "Interval.neg", axiom_interval_neg_ty())?;
1559    Ok(())
1560}
1561#[cfg(test)]
1562mod range_extended_tests {
1563    use super::*;
1564    #[test]
1565    fn test_register_range_extended_succeeds() {
1566        let mut env = Environment::new();
1567        build_range_env(&mut env).expect("build_range_env should succeed");
1568        assert!(register_range_extended(&mut env).is_ok());
1569    }
1570    #[test]
1571    fn test_register_range_extended_axioms_present() {
1572        let mut env = Environment::new();
1573        build_range_env(&mut env).expect("build_range_env should succeed");
1574        register_range_extended(&mut env).expect("unwrap should succeed");
1575        assert!(env.get(&Name::str("Interval")).is_some());
1576        assert!(env.get(&Name::str("Interval.add")).is_some());
1577        assert!(env
1578            .get(&Name::str("MooreArithmetic.fundamental_theorem"))
1579            .is_some());
1580        assert!(env.get(&Name::str("SegmentTree")).is_some());
1581        assert!(env.get(&Name::str("FuzzyInterval")).is_some());
1582        assert!(env.get(&Name::str("ModalInterval")).is_some());
1583    }
1584    #[test]
1585    fn test_float_interval_new() {
1586        let iv = FloatInterval::new(1.0, 3.0);
1587        assert_eq!(iv.lo(), 1.0);
1588        assert_eq!(iv.hi(), 3.0);
1589        assert_eq!(iv.width(), 2.0);
1590        assert_eq!(iv.midpoint(), 2.0);
1591    }
1592    #[test]
1593    fn test_float_interval_contains() {
1594        let iv = FloatInterval::new(0.0, 1.0);
1595        assert!(iv.contains(0.5));
1596        assert!(iv.contains(0.0));
1597        assert!(iv.contains(1.0));
1598        assert!(!iv.contains(-0.1));
1599        assert!(!iv.contains(1.1));
1600    }
1601    #[test]
1602    fn test_float_interval_add() {
1603        let a = FloatInterval::new(1.0, 2.0);
1604        let b = FloatInterval::new(3.0, 4.0);
1605        let c = a.add(b);
1606        assert_eq!(c.lo(), 4.0);
1607        assert_eq!(c.hi(), 6.0);
1608    }
1609    #[test]
1610    fn test_float_interval_sub() {
1611        let a = FloatInterval::new(1.0, 3.0);
1612        let b = FloatInterval::new(1.0, 2.0);
1613        let c = a.sub(b);
1614        assert_eq!(c.lo(), -1.0);
1615        assert_eq!(c.hi(), 2.0);
1616    }
1617    #[test]
1618    fn test_float_interval_mul() {
1619        let a = FloatInterval::new(2.0, 3.0);
1620        let b = FloatInterval::new(4.0, 5.0);
1621        let c = a.mul(b);
1622        assert_eq!(c.lo(), 8.0);
1623        assert_eq!(c.hi(), 15.0);
1624    }
1625    #[test]
1626    fn test_float_interval_neg() {
1627        let a = FloatInterval::new(1.0, 3.0);
1628        let b = a.neg();
1629        assert_eq!(b.lo(), -3.0);
1630        assert_eq!(b.hi(), -1.0);
1631    }
1632    #[test]
1633    fn test_float_interval_intersect() {
1634        let a = FloatInterval::new(1.0, 5.0);
1635        let b = FloatInterval::new(3.0, 8.0);
1636        let c = a.intersect(b).expect("intersect should succeed");
1637        assert_eq!(c.lo(), 3.0);
1638        assert_eq!(c.hi(), 5.0);
1639    }
1640    #[test]
1641    fn test_float_interval_disjoint() {
1642        let a = FloatInterval::new(1.0, 2.0);
1643        let b = FloatInterval::new(3.0, 4.0);
1644        assert!(a.intersect(b).is_none());
1645    }
1646    #[test]
1647    fn test_float_interval_hull() {
1648        let a = FloatInterval::new(1.0, 3.0);
1649        let b = FloatInterval::new(2.0, 5.0);
1650        let h = a.hull(b);
1651        assert_eq!(h.lo(), 1.0);
1652        assert_eq!(h.hi(), 5.0);
1653    }
1654    #[test]
1655    fn test_float_interval_abs_positive() {
1656        let a = FloatInterval::new(2.0, 5.0);
1657        let b = a.abs();
1658        assert_eq!(b.lo(), 2.0);
1659        assert_eq!(b.hi(), 5.0);
1660    }
1661    #[test]
1662    fn test_float_interval_abs_negative() {
1663        let a = FloatInterval::new(-5.0, -2.0);
1664        let b = a.abs();
1665        assert_eq!(b.lo(), 2.0);
1666        assert_eq!(b.hi(), 5.0);
1667    }
1668    #[test]
1669    fn test_float_interval_abs_mixed() {
1670        let a = FloatInterval::new(-3.0, 5.0);
1671        let b = a.abs();
1672        assert_eq!(b.lo(), 0.0);
1673        assert_eq!(b.hi(), 5.0);
1674    }
1675    #[test]
1676    fn test_float_interval_subset() {
1677        let a = FloatInterval::new(2.0, 4.0);
1678        let b = FloatInterval::new(1.0, 5.0);
1679        assert!(a.is_subset_of(b));
1680        assert!(!b.is_subset_of(a));
1681    }
1682    #[test]
1683    fn test_scheduled_job_overlaps() {
1684        let j1 = ScheduledJob::new(0, 0, 5, 1);
1685        let j2 = ScheduledJob::new(1, 3, 8, 1);
1686        let j3 = ScheduledJob::new(2, 5, 10, 1);
1687        assert!(j1.overlaps(&j2));
1688        assert!(!j1.overlaps(&j3));
1689    }
1690    #[test]
1691    fn test_interval_scheduler_basic() {
1692        let jobs = vec![
1693            ScheduledJob::new(0, 0, 3, 3),
1694            ScheduledJob::new(1, 1, 4, 2),
1695            ScheduledJob::new(2, 3, 6, 4),
1696        ];
1697        let mut sched = IntervalScheduler::new(jobs);
1698        let w = sched.max_weight_schedule();
1699        assert!(w >= 4);
1700    }
1701    #[test]
1702    fn test_interval_scheduler_no_overlap() {
1703        let jobs = vec![
1704            ScheduledJob::new(0, 0, 2, 1),
1705            ScheduledJob::new(1, 2, 4, 2),
1706            ScheduledJob::new(2, 4, 6, 3),
1707        ];
1708        let mut sched = IntervalScheduler::new(jobs);
1709        let w = sched.max_weight_schedule();
1710        assert_eq!(w, 6);
1711    }
1712    #[test]
1713    fn test_seg_tree_build_query() {
1714        let values = vec![5i64, 3, 7, 1, 9, 2];
1715        let tree = RangeMinSegTree::build(&values);
1716        assert_eq!(tree.query_min(0, 5), Some(1));
1717        assert_eq!(tree.query_min(0, 2), Some(3));
1718        assert_eq!(tree.query_min(3, 5), Some(1));
1719    }
1720    #[test]
1721    fn test_seg_tree_update() {
1722        let values = vec![5i64, 3, 7, 1, 9, 2];
1723        let mut tree = RangeMinSegTree::build(&values);
1724        tree.update(3, 10);
1725        assert_eq!(tree.query_min(0, 5), Some(2));
1726    }
1727    #[test]
1728    fn test_seg_tree_empty() {
1729        let tree = RangeMinSegTree::build(&[]);
1730        assert!(tree.is_empty());
1731        assert_eq!(tree.query_min(0, 0), None);
1732    }
1733    #[test]
1734    fn test_krawczyk_finds_root_of_linear() {
1735        let solver = KrawczykSolver::new(50, 1e-10);
1736        let x0 = FloatInterval::new(1.0, 3.0);
1737        let result = solver.solve(x0, |x| x - 2.0, |_iv| FloatInterval::new(1.0, 1.0));
1738        assert!(result.is_some());
1739        let root_iv = result.expect("result should be valid");
1740        assert!(root_iv.contains(2.0));
1741    }
1742    #[test]
1743    fn test_validated_interval_verified() {
1744        let iv = FloatInterval::new(1.0, 2.0);
1745        let vi = ValidatedInterval::verified(iv, "test");
1746        assert!(vi.is_verified());
1747        assert_eq!(vi.certificate(), "test");
1748    }
1749    #[test]
1750    fn test_validated_interval_add() {
1751        let a = ValidatedInterval::verified(FloatInterval::new(1.0, 2.0), "a");
1752        let b = ValidatedInterval::verified(FloatInterval::new(3.0, 4.0), "b");
1753        let c = a.add(&b);
1754        assert!(c.is_verified());
1755        assert_eq!(c.interval().lo(), 4.0);
1756        assert_eq!(c.interval().hi(), 6.0);
1757    }
1758    #[test]
1759    fn test_validated_interval_unverified_propagates() {
1760        let a = ValidatedInterval::verified(FloatInterval::new(1.0, 2.0), "a");
1761        let b = ValidatedInterval::unverified(FloatInterval::new(3.0, 4.0));
1762        let c = a.add(&b);
1763        assert!(!c.is_verified());
1764    }
1765    #[test]
1766    fn test_axiom_type_builders_interval() {
1767        let _ = axiom_interval_type_ty();
1768        let _ = axiom_interval_mk_ty();
1769        let _ = axiom_interval_add_ty();
1770        let _ = axiom_interval_mul_ty();
1771        let _ = axiom_interval_width_ty();
1772        let _ = axiom_interval_midpoint_ty();
1773        let _ = axiom_interval_newton_step_ty();
1774        let _ = axiom_krawczyk_operator_ty();
1775        let _ = axiom_segment_tree_query_ty();
1776        let _ = axiom_interval_scheduling_optimal_ty();
1777    }
1778}