Skip to main content

litex/to_latex/
to_latex_string.rs

1use crate::prelude::*;
2
3fn chain_link_infix_latex(prop: &str) -> Option<&'static str> {
4    if prop == EQUAL {
5        Some("=")
6    } else if prop == NOT_EQUAL {
7        Some(r"\neq")
8    } else if prop == LESS {
9        Some("<")
10    } else if prop == GREATER {
11        Some(">")
12    } else if prop == LESS_EQUAL {
13        Some(r"\leq")
14    } else if prop == GREATER_EQUAL {
15        Some(r"\geq")
16    } else if prop == IN {
17        Some(r"\in")
18    } else {
19        None
20    }
21}
22
23fn latex_escape_underscore(s: &str) -> String {
24    s.replace('_', r"\_")
25}
26
27fn latex_local_ident(name: &str) -> String {
28    format!(r"\mathit{{{}}}", latex_escape_underscore(name))
29}
30
31fn latex_texttt_escape(s: &str) -> String {
32    let mut out = String::new();
33    for ch in s.chars() {
34        match ch {
35            '_' | '%' | '#' | '&' | '$' => {
36                out.push('\\');
37                out.push(ch);
38            }
39            '{' => out.push_str(r"\{"),
40            '}' => out.push_str(r"\}"),
41            '\\' => out.push_str(r"\textbackslash{}"),
42            '^' => out.push_str(r"\textasciicircum{}"),
43            '~' => out.push_str(r"\textasciitilde{}"),
44            _ => out.push(ch),
45        }
46    }
47    out
48}
49
50fn fn_set_clause_latex(clause: &FnSetClause) -> String {
51    let mut slots: Vec<String> = Vec::new();
52    for g in &clause.params_def_with_set {
53        let set = g.set.to_latex_string();
54        for p in &g.params {
55            slots.push(format!(r"{} \in {}", latex_local_ident(p), set));
56        }
57    }
58    let dom = clause
59        .dom_facts
60        .iter()
61        .map(|f| f.to_latex_string())
62        .collect::<Vec<_>>()
63        .join(r", ");
64    let ret = clause.ret_set.to_latex_string();
65    if dom.is_empty() {
66        format!(
67            r"\mathrm{{fn}}\left({}\right)\to {}",
68            slots.join(r", "),
69            ret
70        )
71    } else {
72        format!(
73            r"\mathrm{{fn}}\left({} \,\middle|\, {}\right)\to {}",
74            slots.join(r", "),
75            dom,
76            ret
77        )
78    }
79}
80
81impl AndChainAtomicFact {
82    pub fn to_latex_string(&self) -> String {
83        match self {
84            AndChainAtomicFact::AtomicFact(x) => x.to_latex_string(),
85            AndChainAtomicFact::AndFact(x) => x.to_latex_string(),
86            AndChainAtomicFact::ChainFact(x) => x.to_latex_string(),
87        }
88    }
89}
90
91impl OrAndChainAtomicFact {
92    pub fn to_latex_string(&self) -> String {
93        match self {
94            OrAndChainAtomicFact::AtomicFact(x) => x.to_latex_string(),
95            OrAndChainAtomicFact::AndFact(x) => x.to_latex_string(),
96            OrAndChainAtomicFact::ChainFact(x) => x.to_latex_string(),
97            OrAndChainAtomicFact::OrFact(x) => x.to_latex_string(),
98        }
99    }
100}
101
102impl AndFact {
103    pub fn to_latex_string(&self) -> String {
104        self.facts
105            .iter()
106            .map(|a| a.to_latex_string())
107            .collect::<Vec<_>>()
108            .join(r" \land ")
109    }
110}
111
112impl ChainFact {
113    pub fn to_latex_string(&self) -> String {
114        if self.objs.is_empty() {
115            return String::new();
116        }
117        let mut s = self.objs[0].to_latex_string();
118        for (i, obj) in self.objs[1..].iter().enumerate() {
119            let pname = self.prop_names[i].to_string();
120            let rhs = obj.to_latex_string();
121            if let Some(op) = chain_link_infix_latex(&pname) {
122                s.push(' ');
123                s.push_str(op);
124                s.push(' ');
125                s.push_str(&rhs);
126            } else if is_comparison_str(&pname) {
127                s.push(' ');
128                s.push_str(&pname);
129                s.push(' ');
130                s.push_str(&rhs);
131            } else {
132                s.push_str(&format!(r" \mathrel{{\mathrm{{{}}}}} {}", pname, rhs));
133            }
134        }
135        s
136    }
137}
138
139impl Abs {
140    pub fn to_latex_string(&self) -> String {
141        format!(r"\left| {} \right|", self.arg.to_latex_string())
142    }
143}
144
145impl Add {
146    pub fn to_latex_string(&self) -> String {
147        format!(
148            "{} + {}",
149            self.left.to_latex_string(),
150            self.right.to_latex_string()
151        )
152    }
153}
154
155impl ByCasesStmt {
156    pub fn to_latex_string(&self) -> String {
157        let goal = self
158            .then_facts
159            .iter()
160            .map(|f| f.to_latex_string())
161            .collect::<Vec<_>>()
162            .join(r" \land ");
163        let mut rows: Vec<String> = Vec::new();
164        rows.push(format!(r"\text{{Proof by cases. Goal:}} & {}", goal));
165        for (i, ((case, proof), imposs)) in self
166            .cases
167            .iter()
168            .zip(self.proofs.iter())
169            .zip(self.impossible_facts.iter())
170            .enumerate()
171        {
172            rows.push(format!(
173                r"\textbf{{\text{{Case {}.}}}} & {}",
174                i + 1,
175                case.to_latex_string()
176            ));
177            for st in proof {
178                rows.push(format!(r"& \quad {}", st.to_latex_string()));
179            }
180            if let Some(atom) = imposs {
181                rows.push(format!(
182                    r"\textbf{{\text{{Impossible.}}}} & {}",
183                    atom.to_latex_string()
184                ));
185            }
186        }
187        format!(
188            "\\begin{{aligned}}\n{}\n\\end{{aligned}}",
189            rows.join(" \\\\\n")
190        )
191    }
192}
193
194impl ByContraStmt {
195    pub fn to_latex_string(&self) -> String {
196        let goal = self.to_prove.to_latex_string();
197        let mut rows = vec![format!(
198            r"\text{{Proof by contradiction. Goal:}} & {}",
199            goal
200        )];
201        for st in &self.proof {
202            rows.push(format!(r"& \quad {}", st.to_latex_string()));
203        }
204        rows.push(format!(
205            r"\textbf{{\text{{Contradiction.}}}} & {}",
206            self.impossible_fact.to_latex_string()
207        ));
208        format!(
209            "\\begin{{aligned}}\n{}\n\\end{{aligned}}",
210            rows.join(" \\\\\n")
211        )
212    }
213}
214
215impl ByEnumerateClosedRangeStmt {
216    pub fn to_latex_string(&self) -> String {
217        let a = self.closed_range.start.to_latex_string();
218        let b = self.closed_range.end.to_latex_string();
219        let x = self.element.to_latex_string();
220        let row1 = format!(
221            r"&\text{{\textbf{{By enumeration}} on the closed integer interval }} [\![ {0},{1}]\!]\text{{.}}",
222            a, b
223        );
224        let row2 = format!(
225            r"&\text{{Equivalently }} {0} \in \{{{1},\, {1}+1,\, \ldots,\, {2}\}}\text{{ (segment {1}\ldots {2}).}}",
226            x, a, b
227        );
228        let row3 = format!(
229            r"&\text{{So }} {0}={1}\lor {0}={1}+1\lor\cdots\lor {0}={2}\text{{.}}",
230            x, a, b
231        );
232        format!("\\begin{{aligned}}\n{row1} \\\\\n{row2} \\\\\n{row3} \n\\end{{aligned}}")
233    }
234}
235
236impl ByEnumerateFiniteSetStmt {
237    pub fn to_latex_string(&self) -> String {
238        let mut rows = vec![format!(
239            r"\text{{Proof by exhaustive enumeration (finite cases).}} & {}",
240            self.forall_fact.to_latex_string()
241        )];
242        for st in &self.proof {
243            rows.push(format!(r"& \quad {}", st.to_latex_string()));
244        }
245        format!(
246            "\\begin{{aligned}}\n{}\n\\end{{aligned}}",
247            rows.join(" \\\\\n")
248        )
249    }
250}
251
252impl ByExtensionStmt {
253    pub fn to_latex_string(&self) -> String {
254        let l = self.left.to_latex_string();
255        let r = self.right.to_latex_string();
256        let mut rows = vec![format!(
257            r"\text{{\textbf{{By extensionality}}:}} & {}={} \Longleftrightarrow \bigl({}\subseteq {}\land {}\subseteq {}\bigr)\text{{.}}",
258            l, r, l, r, r, l
259        )];
260        for st in &self.proof {
261            rows.push(format!(r"& \quad {}", st.to_latex_string()));
262        }
263        format!(
264            "\\begin{{aligned}}\n{}\n\\end{{aligned}}",
265            rows.join(" \\\\\n")
266        )
267    }
268}
269
270impl ByFamilyStmt {
271    pub fn to_latex_string(&self) -> String {
272        format!(
273            "\\begin{{aligned}}\n\\text{{\\textbf{{By family}}:}} & \\text{{Use the set-theoretic definition of }} {}\\text{{; obtain the corresponding set characterization.}}\n\\end{{aligned}}",
274            self.family_obj.to_latex_string()
275        )
276    }
277}
278
279impl ByFnSetStmt {
280    pub fn to_latex_string(&self) -> String {
281        format!(
282            "\\begin{{aligned}}\n\\text{{\\textbf{{By fn set}}:}} & {} \\in {}\\\\\n& \\quad \\text{{Unfold this membership via the set-theoretic definition of the function space; obtain the corresponding facts.}}\n\\end{{aligned}}",
283            self.func.to_latex_string(),
284            self.fn_set.to_latex_string()
285        )
286    }
287}
288
289impl ByFnStmt {
290    pub fn to_latex_string(&self) -> String {
291        format!(
292            "\\begin{{aligned}}\n\\text{{\\textbf{{By fn}}:}} & \\text{{Use the graph / function definition of }} {}\\text{{.}}\n\\end{{aligned}}",
293            self.function.to_latex_string()
294        )
295    }
296}
297
298impl ByForStmt {
299    pub fn to_latex_string(&self) -> String {
300        let mut rows = vec![format!(
301            r"\text{{\textbf{{by for}}:}} & {}",
302            self.forall_fact.to_latex_string()
303        )];
304        for st in &self.proof {
305            rows.push(format!(r"& \quad {}", st.to_latex_string()));
306        }
307        format!(
308            "\\begin{{aligned}}\n{}\n\\end{{aligned}}",
309            rows.join(" \\\\\n")
310        )
311    }
312}
313
314impl ByInducStmt {
315    pub fn to_latex_string(&self) -> String {
316        let goals = self
317            .to_prove
318            .iter()
319            .map(|f| f.to_latex_string())
320            .collect::<Vec<_>>()
321            .join(r" \land ");
322        let induc_label = if self.strong {
323            r"\text{\textbf{strong induc} on }"
324        } else {
325            r"\text{\textbf{by induc} on }"
326        };
327        let mut rows = vec![format!(
328            r"{} {} \text{{ from }} {} \texttt{{:}} & {}",
329            induc_label,
330            latex_local_ident(&self.param),
331            self.induc_from.to_latex_string(),
332            goals
333        )];
334        rows.push(r"\text{prove:} &".to_string());
335        for st in &self.proof {
336            rows.push(format!(r"& \quad {}", st.to_latex_string()));
337        }
338        format!(
339            "\\begin{{aligned}}\n{}\n\\end{{aligned}}",
340            rows.join(" \\\\\n")
341        )
342    }
343}
344
345impl ByTupleStmt {
346    pub fn to_latex_string(&self) -> String {
347        format!(
348            "\\begin{{aligned}}\n\\text{{\\textbf{{By tuple}}:}} & \\text{{Use the set-theoretic ordered-pair / tuple encoding for }} {}\\text{{; obtain the corresponding set-theoretic facts.}}\n\\end{{aligned}}",
349            self.obj.to_latex_string()
350        )
351    }
352}
353
354impl Cap {
355    pub fn to_latex_string(&self) -> String {
356        format!(
357            r"\operatorname{{{}}}\left( {}\right)",
358            CAP,
359            self.left.to_latex_string()
360        )
361    }
362}
363
364impl Cart {
365    pub fn to_latex_string(&self) -> String {
366        let inner = self
367            .args
368            .iter()
369            .map(|o| o.to_latex_string())
370            .collect::<Vec<_>>()
371            .join(", ");
372        format!(r"\operatorname{{{}}}\left( {}\right)", CART, inner)
373    }
374}
375
376impl CartDim {
377    pub fn to_latex_string(&self) -> String {
378        format!(
379            r"\operatorname{{{}}}\left( {}\right)",
380            CART_DIM,
381            self.set.to_latex_string()
382        )
383    }
384}
385
386impl ClaimStmt {
387    pub fn to_latex_string(&self) -> String {
388        let mut rows = vec![
389            format!(
390                r"\text{{\textbf{{claim}}:}} & {}",
391                self.fact.to_latex_string()
392            ),
393            r"\text{\textbf{prove}:} &".to_string(),
394        ];
395        for st in &self.proof {
396            rows.push(format!(r"& \quad {}", st.to_latex_string()));
397        }
398        format!(
399            "\\begin{{aligned}}\n{}\n\\end{{aligned}}",
400            rows.join(" \\\\\n")
401        )
402    }
403}
404
405impl ClosedRange {
406    pub fn to_latex_string(&self) -> String {
407        format!(
408            r"\operatorname{{{}}}\left( {}, {} \right)",
409            CLOSED_RANGE,
410            self.start.to_latex_string(),
411            self.end.to_latex_string()
412        )
413    }
414}
415
416impl Count {
417    pub fn to_latex_string(&self) -> String {
418        format!(
419            r"\operatorname{{{}}}\left( {}\right)",
420            COUNT,
421            self.set.to_latex_string()
422        )
423    }
424}
425
426impl Sum {
427    pub fn to_latex_string(&self) -> String {
428        format!(
429            r"\operatorname{{{}}}\left( {}, {}, {} \right)",
430            SUM,
431            self.start.to_latex_string(),
432            self.end.to_latex_string(),
433            self.func.to_latex_string()
434        )
435    }
436}
437
438impl Product {
439    pub fn to_latex_string(&self) -> String {
440        format!(
441            r"\operatorname{{{}}}\left( {}, {}, {} \right)",
442            PRODUCT,
443            self.start.to_latex_string(),
444            self.end.to_latex_string(),
445            self.func.to_latex_string()
446        )
447    }
448}
449
450impl Cup {
451    pub fn to_latex_string(&self) -> String {
452        format!(
453            r"\operatorname{{{}}}\left( {}\right)",
454            CUP,
455            self.left.to_latex_string()
456        )
457    }
458}
459
460impl Choose {
461    pub fn to_latex_string(&self) -> String {
462        format!(
463            r"\operatorname{{{}}}\left( {}\right)",
464            CHOOSE,
465            self.set.to_latex_string()
466        )
467    }
468}
469
470impl DefAbstractPropStmt {
471    pub fn to_latex_string(&self) -> String {
472        let ps = self
473            .params
474            .iter()
475            .map(|p| latex_local_ident(p))
476            .collect::<Vec<_>>()
477            .join(", ");
478        format!(
479            r"\operatorname{{{}}}\, {}\left\{{ {} \right\}}",
480            ABSTRACT_PROP,
481            latex_local_ident(&self.name),
482            ps
483        )
484    }
485}
486
487impl DefAlgoStmt {
488    pub fn to_latex_string(&self) -> String {
489        let ps = self
490            .params
491            .iter()
492            .map(|p| latex_local_ident(p))
493            .collect::<Vec<_>>()
494            .join(", ");
495        let mut rows = vec![format!(
496            r"\operatorname{{{}}}\, {}\left( {}\right) \texttt{{:}}",
497            ALGO,
498            latex_local_ident(&self.name),
499            ps
500        )];
501        for c in &self.cases {
502            rows.push(format!(
503                r"& \quad \mathrm{{case}}\ {} \texttt{{:}}\ {}",
504                c.condition.to_latex_string(),
505                c.return_stmt.value.to_latex_string()
506            ));
507        }
508        if let Some(dr) = &self.default_return {
509            rows.push(format!(
510                r"& \quad \mathrm{{default}}\ \texttt{{:}}\ {}",
511                dr.value.to_latex_string()
512            ));
513        }
514        format!(
515            "\\begin{{aligned}}\n{}\n\\end{{aligned}}",
516            rows.join(" \\\\\n")
517        )
518    }
519}
520
521impl DefFamilyStmt {
522    pub fn to_latex_string(&self) -> String {
523        let dom = self
524            .dom_facts
525            .iter()
526            .map(|f| f.to_latex_string())
527            .collect::<Vec<_>>()
528            .join(r", ");
529        format!(
530            r"\operatorname{{{}}}\, {}\left( {} : {} \right) = {}",
531            FAMILY,
532            latex_local_ident(&self.name),
533            self.params_def_with_type.to_latex_string(),
534            dom,
535            self.equal_to.to_latex_string()
536        )
537    }
538}
539
540impl DefLetStmt {
541    pub fn to_latex_string(&self) -> String {
542        match self.facts.len() {
543            0 => format!(
544                r"\operatorname{{{}}}\, {}",
545                LET,
546                self.param_def.to_latex_string()
547            ),
548            _ => {
549                let mut rows = vec![format!(
550                    r"\operatorname{{{}}}\, {}",
551                    LET,
552                    self.param_def.to_latex_string()
553                )];
554                for fact in &self.facts {
555                    rows.push(format!(r"& \quad {}", fact.to_latex_string()));
556                }
557                format!(
558                    "\\begin{{aligned}}\n{}\n\\end{{aligned}}",
559                    rows.join(" \\\\\n")
560                )
561            }
562        }
563    }
564}
565
566impl DefPropStmt {
567    pub fn to_latex_string(&self) -> String {
568        match self.iff_facts.len() {
569            0 => format!(
570                r"\operatorname{{{}}}\, {}\left\{{ {} \right\}}",
571                PROP,
572                latex_local_ident(&self.name),
573                self.params_def_with_type.to_latex_string()
574            ),
575            _ => {
576                let mut rows = vec![format!(
577                    r"\operatorname{{{}}}\, {}\left\{{ {} \right\}} \texttt{{:}}",
578                    PROP,
579                    latex_local_ident(&self.name),
580                    self.params_def_with_type.to_latex_string()
581                )];
582                for fact in &self.iff_facts {
583                    rows.push(format!(r"& \quad {}", fact.to_latex_string()));
584                }
585                format!(
586                    "\\begin{{aligned}}\n{}\n\\end{{aligned}}",
587                    rows.join(" \\\\\n")
588                )
589            }
590        }
591    }
592}
593
594impl Div {
595    pub fn to_latex_string(&self) -> String {
596        format!(
597            r"\frac{{{}}}{{{}}}",
598            self.left.to_latex_string(),
599            self.right.to_latex_string()
600        )
601    }
602}
603
604impl DoNothingStmt {
605    pub fn to_latex_string(&self) -> String {
606        format!(r"\mathrm{{{}}}", DO_NOTHING)
607    }
608}
609
610impl ClearStmt {
611    pub fn to_latex_string(&self) -> String {
612        format!(r"\mathrm{{{}}}", CLEAR)
613    }
614}
615
616impl EqualFact {
617    pub fn to_latex_string(&self) -> String {
618        format!(
619            "{} = {}",
620            self.left.to_latex_string(),
621            self.right.to_latex_string()
622        )
623    }
624}
625
626impl EvalStmt {
627    pub fn to_latex_string(&self) -> String {
628        format!(
629            r"\operatorname{{{}}}\, {}",
630            EVAL,
631            self.obj_to_eval.to_latex_string()
632        )
633    }
634}
635
636impl ExistFactEnum {
637    pub fn to_latex_string(&self) -> String {
638        let head = if self.is_not_exist() {
639            r"\nexists"
640        } else if self.is_exist_unique() {
641            r"\exists!"
642        } else {
643            r"\exists"
644        };
645        let params = self.params_def_with_type().to_latex_string();
646        let facts = self
647            .facts()
648            .iter()
649            .map(|f| f.to_latex_string())
650            .collect::<Vec<_>>()
651            .join(r", ");
652        format!(
653            r"{}\, \left( {}\right)\, \mathrm{{st}}\, \left\{{ {} \right\}}",
654            head, params, facts
655        )
656    }
657}
658
659impl ExistBodyFact {
660    pub fn to_latex_string(&self) -> String {
661        match self {
662            ExistBodyFact::AtomicFact(x) => x.to_latex_string(),
663            ExistBodyFact::AndFact(x) => x.to_latex_string(),
664            ExistBodyFact::ChainFact(x) => x.to_latex_string(),
665            ExistBodyFact::OrFact(x) => x.to_latex_string(),
666            ExistBodyFact::InlineForall(x) => x.to_latex_string(),
667        }
668    }
669}
670
671impl ExistOrAndChainAtomicFact {
672    pub fn to_latex_string(&self) -> String {
673        match self {
674            ExistOrAndChainAtomicFact::AtomicFact(x) => x.to_latex_string(),
675            ExistOrAndChainAtomicFact::AndFact(x) => x.to_latex_string(),
676            ExistOrAndChainAtomicFact::ChainFact(x) => x.to_latex_string(),
677            ExistOrAndChainAtomicFact::OrFact(x) => x.to_latex_string(),
678            ExistOrAndChainAtomicFact::ExistFact(x) => x.to_latex_string(),
679        }
680    }
681}
682
683impl FamilyObj {
684    pub fn to_latex_string(&self) -> String {
685        let head = self.name.to_latex_string();
686        let args = self
687            .params
688            .iter()
689            .map(|o| o.to_latex_string())
690            .collect::<Vec<_>>()
691            .join(", ");
692        format!(r"\operatorname{{{}}}\left( {}\right)", head, args)
693    }
694}
695
696impl FiniteSeqListObj {
697    pub fn to_latex_string(&self) -> String {
698        let inner = self
699            .objs
700            .iter()
701            .map(|o| o.to_latex_string())
702            .collect::<Vec<_>>()
703            .join(", ");
704        format!(r"\left[ {} \right]", inner)
705    }
706}
707
708impl FiniteSeqSet {
709    pub fn to_latex_string(&self) -> String {
710        format!(
711            r"\operatorname{{{}}}\left( {}, {} \right)",
712            FINITE_SEQ,
713            self.set.to_latex_string(),
714            self.n.to_latex_string()
715        )
716    }
717}
718
719impl FnObj {
720    pub fn to_latex_string(&self) -> String {
721        let head = match self.head.as_ref() {
722            FnObjHead::Identifier(i) => i.to_latex_string(),
723            FnObjHead::IdentifierWithMod(i) => i.to_latex_string(),
724            FnObjHead::Forall(p) => latex_local_ident(&p.name),
725            FnObjHead::DefHeader(p) => latex_local_ident(&p.name),
726            FnObjHead::Exist(p) => latex_local_ident(&p.name),
727            FnObjHead::SetBuilder(p) => latex_local_ident(&p.name),
728            FnObjHead::FnSet(p) => latex_local_ident(&p.name),
729            FnObjHead::AnonymousFnLiteral(a) => a.to_latex_string(),
730            FnObjHead::Induc(p) => latex_local_ident(&p.name),
731            FnObjHead::DefAlgo(p) => latex_local_ident(&p.name),
732        };
733        let mut s = head;
734        for group in self.body.iter() {
735            let inner = group
736                .iter()
737                .map(|o| o.to_latex_string())
738                .collect::<Vec<_>>()
739                .join(", ");
740            s.push_str(&format!(r"\left( {} \right)", inner));
741        }
742        s
743    }
744}
745
746impl AnonymousFn {
747    pub fn to_latex_string(&self) -> String {
748        let mut slots: Vec<String> = Vec::new();
749        for g in &self.body.params_def_with_set {
750            let set = g.set.to_latex_string();
751            for p in &g.params {
752                slots.push(format!(r"{} \in {}", latex_local_ident(p), set));
753            }
754        }
755        let dom = self
756            .body
757            .dom_facts
758            .iter()
759            .map(|f| f.to_latex_string())
760            .collect::<Vec<_>>()
761            .join(r", ");
762        let ret = self.body.ret_set.to_latex_string();
763        let body = self.equal_to.to_latex_string();
764        let sig = if dom.is_empty() {
765            format!(r"\left({}\right)", slots.join(r", "))
766        } else {
767            format!(r"\left({} \,\middle|\, {}\right)", slots.join(r", "), dom)
768        };
769        format!(
770            r"'\, {} \to {} \mapsto \left\{{ {}\right\}}",
771            sig, ret, body
772        )
773    }
774}
775
776impl FnSet {
777    pub fn to_latex_string(&self) -> String {
778        let mut slots: Vec<String> = Vec::new();
779        for g in &self.body.params_def_with_set {
780            let set = g.set.to_latex_string();
781            for p in &g.params {
782                slots.push(format!(r"{} \in {}", latex_local_ident(p), set));
783            }
784        }
785        let dom = self
786            .body
787            .dom_facts
788            .iter()
789            .map(|f| f.to_latex_string())
790            .collect::<Vec<_>>()
791            .join(r", ");
792        let ret = self.body.ret_set.to_latex_string();
793        if dom.is_empty() {
794            format!(
795                r"\mathrm{{fn}}\left({}\right)\to {}",
796                slots.join(r", "),
797                ret
798            )
799        } else {
800            format!(
801                r"\mathrm{{fn}}\left({} \,\middle|\, {}\right)\to {}",
802                slots.join(r", "),
803                dom,
804                ret
805            )
806        }
807    }
808}
809
810impl ForallFact {
811    pub fn to_latex_string(&self) -> String {
812        let params = self.params_def_with_type.to_latex_string();
813        let then = self
814            .then_facts
815            .iter()
816            .map(|f| f.to_latex_string())
817            .collect::<Vec<_>>()
818            .join(r" \land ");
819        if self.dom_facts.is_empty() {
820            format!(r"\forall \left( {}\right),\, {}", params, then)
821        } else {
822            let dom = self
823                .dom_facts
824                .iter()
825                .map(|f| f.to_latex_string())
826                .collect::<Vec<_>>()
827                .join(r" \land ");
828            format!(
829                r"\forall \left( {}\right),\ \left( {}\right) \Rightarrow \left( {}\right)",
830                params, dom, then
831            )
832        }
833    }
834}
835
836impl ForallFactWithIff {
837    pub fn to_latex_string(&self) -> String {
838        let iff = self
839            .iff_facts
840            .iter()
841            .map(|f| f.to_latex_string())
842            .collect::<Vec<_>>()
843            .join(r" \land ");
844        format!(
845            r"{}\, \Longleftrightarrow\, \left( {}\right)",
846            self.forall_fact.to_latex_string(),
847            iff
848        )
849    }
850}
851
852impl NotForallFact {
853    pub fn to_latex_string(&self) -> String {
854        format!(
855            r"\neg\, \left( {}\right)",
856            self.forall_fact.to_latex_string()
857        )
858    }
859}
860
861impl GreaterEqualFact {
862    pub fn to_latex_string(&self) -> String {
863        format!(
864            r"{} \geq {}",
865            self.left.to_latex_string(),
866            self.right.to_latex_string()
867        )
868    }
869}
870
871impl GreaterFact {
872    pub fn to_latex_string(&self) -> String {
873        format!(
874            "{} > {}",
875            self.left.to_latex_string(),
876            self.right.to_latex_string()
877        )
878    }
879}
880
881impl HaveByExistStmt {
882    pub fn to_latex_string(&self) -> String {
883        let names = self
884            .equal_tos
885            .iter()
886            .map(|s| latex_local_ident(s))
887            .collect::<Vec<_>>()
888            .join(", ");
889        format!(
890            r"\mathrm{{have}}\ \mathrm{{by}}\ {} : {}",
891            self.exist_fact_in_have_obj_st.to_latex_string(),
892            names
893        )
894    }
895}
896
897impl HaveFnByInducStmt {
898    pub fn to_latex_string(&self) -> String {
899        let mut rows: Vec<String> = Vec::new();
900        rows.push(format!(
901            r"\mathrm{{have}}\ \mathrm{{fn}}\ \mathrm{{by}}\ \mathrm{{induc}}\ \mathrm{{from}}\ {} \texttt{{:}}\ \mathrm{{fn}}\ {}\left( {} : {} \geq {} \right) {}",
902            self.induc_from.to_latex_string(),
903            latex_local_ident(&self.name),
904            latex_local_ident(&self.param),
905            Z,
906            self.induc_from.to_latex_string(),
907            self.ret_set.to_latex_string()
908        ));
909        for (i, eq) in self.special_cases_equal_tos.iter().enumerate() {
910            rows.push(format!(
911                r"& \quad \mathrm{{case}}\ {} : {}",
912                i,
913                eq.to_latex_string()
914            ));
915        }
916        let n = self.special_cases_equal_tos.len();
917        match &self.last_case {
918            HaveFnByInducLastCase::EqualTo(eq) => {
919                rows.push(format!(
920                    r"& \quad \mathrm{{case}}\ \geq {} : {}",
921                    n,
922                    eq.to_latex_string()
923                ));
924            }
925            HaveFnByInducLastCase::NestedCases(nc) => {
926                rows.push(format!(r"& \quad \mathrm{{case}}\ \geq {} \texttt{{:}}", n));
927                for c in nc {
928                    rows.push(format!(
929                        r"& \quad \quad \mathrm{{case}}\ {} : {}",
930                        c.case_fact.to_latex_string(),
931                        c.equal_to.to_latex_string()
932                    ));
933                }
934            }
935        }
936        format!(
937            "\\begin{{aligned}}\n{}\n\\end{{aligned}}",
938            rows.join(" \\\\\n")
939        )
940    }
941}
942
943impl HaveFnEqualCaseByCaseStmt {
944    pub fn to_latex_string(&self) -> String {
945        let head = format!(
946            r"\mathrm{{have}}\ \mathrm{{fn}}\ {}\ \texttt{{=}} \texttt{{:}}",
947            latex_local_ident(&self.name)
948        );
949        let clause = fn_set_clause_latex(&self.fn_set_clause);
950        let mut rows = vec![format!(r"{} & {}", head, clause)];
951        for (i, case) in self.cases.iter().enumerate() {
952            rows.push(format!(
953                r"& \quad \mathrm{{case}}\ {} \texttt{{:}}\ {} = {}",
954                case.to_latex_string(),
955                latex_local_ident(&self.name),
956                self.equal_tos[i].to_latex_string()
957            ));
958        }
959        format!(
960            "\\begin{{aligned}}\n{}\n\\end{{aligned}}",
961            rows.join(" \\\\\n")
962        )
963    }
964}
965
966impl HaveFnEqualStmt {
967    pub fn to_latex_string(&self) -> String {
968        let fn_set_clause = FnSetClause::new(
969            self.equal_to_anonymous_fn.body.params_def_with_set.clone(),
970            self.equal_to_anonymous_fn.body.dom_facts.clone(),
971            (*self.equal_to_anonymous_fn.body.ret_set).clone(),
972        );
973        format!(
974            r"\mathrm{{have}}\ \mathrm{{fn}}\ {}\ {} {}",
975            latex_local_ident(&self.name),
976            fn_set_clause_latex(&fn_set_clause),
977            self.equal_to_anonymous_fn.equal_to.to_latex_string()
978        )
979    }
980}
981
982impl HaveObjEqualStmt {
983    pub fn to_latex_string(&self) -> String {
984        let rhs = self
985            .objs_equal_to
986            .iter()
987            .map(|o| o.to_latex_string())
988            .collect::<Vec<_>>()
989            .join(", ");
990        format!(
991            r"\mathrm{{have}}\ {} = {}",
992            self.param_def.to_latex_string(),
993            rhs
994        )
995    }
996}
997
998impl HaveObjInNonemptySetOrParamTypeStmt {
999    pub fn to_latex_string(&self) -> String {
1000        format!(r"\mathrm{{have}}\ {}", self.param_def.to_latex_string())
1001    }
1002}
1003
1004impl Identifier {
1005    pub fn to_latex_string(&self) -> String {
1006        latex_local_ident(&self.name)
1007    }
1008}
1009
1010impl IdentifierWithMod {
1011    pub fn to_latex_string(&self) -> String {
1012        format!(
1013            r"{}\mathbin{{\mathrm{{::}}}}{}",
1014            latex_local_ident(&self.mod_name),
1015            latex_local_ident(&self.name)
1016        )
1017    }
1018}
1019
1020impl AtomicName {
1021    pub fn to_latex_string(&self) -> String {
1022        match self {
1023            AtomicName::WithoutMod(s) => latex_local_ident(s),
1024            AtomicName::WithMod(m, n) => format!(
1025                r"{}\mathbin{{\mathrm{{::}}}}{}",
1026                latex_local_ident(m),
1027                latex_local_ident(n)
1028            ),
1029        }
1030    }
1031}
1032
1033impl InFact {
1034    pub fn to_latex_string(&self) -> String {
1035        format!(
1036            r"{} \in {}",
1037            self.element.to_latex_string(),
1038            self.set.to_latex_string()
1039        )
1040    }
1041}
1042
1043impl Intersect {
1044    pub fn to_latex_string(&self) -> String {
1045        format!(
1046            r"{} \cap {}",
1047            self.left.to_latex_string(),
1048            self.right.to_latex_string()
1049        )
1050    }
1051}
1052
1053impl IsCartFact {
1054    pub fn to_latex_string(&self) -> String {
1055        format!(
1056            r"\$ \mathrm{{{}}}\left( {}\right)",
1057            IS_CART,
1058            self.set.to_latex_string()
1059        )
1060    }
1061}
1062
1063impl IsFiniteSetFact {
1064    pub fn to_latex_string(&self) -> String {
1065        format!(
1066            r"\$ \mathrm{{{}}}\left( {}\right)",
1067            IS_FINITE_SET,
1068            self.set.to_latex_string()
1069        )
1070    }
1071}
1072
1073impl IsNonemptySetFact {
1074    pub fn to_latex_string(&self) -> String {
1075        format!(
1076            r"\$ \mathrm{{{}}}\left( {}\right)",
1077            IS_NONEMPTY_SET,
1078            self.set.to_latex_string()
1079        )
1080    }
1081}
1082
1083impl IsSetFact {
1084    pub fn to_latex_string(&self) -> String {
1085        format!(
1086            r"\$ \mathrm{{{}}}\left( {}\right)",
1087            IS_SET,
1088            self.set.to_latex_string()
1089        )
1090    }
1091}
1092
1093impl IsTupleFact {
1094    pub fn to_latex_string(&self) -> String {
1095        format!(
1096            r"\$ \mathrm{{{}}}\left( {}\right)",
1097            IS_TUPLE,
1098            self.set.to_latex_string()
1099        )
1100    }
1101}
1102
1103impl KnowStmt {
1104    pub fn to_latex_string(&self) -> String {
1105        if self.facts.len() == 1 {
1106            format!(
1107                r"\operatorname{{{}}} {}",
1108                KNOW,
1109                self.facts[0].to_latex_string()
1110            )
1111        } else {
1112            let rows = self
1113                .facts
1114                .iter()
1115                .map(|fact| format!("& {}", fact.to_latex_string()))
1116                .collect::<Vec<_>>()
1117                .join(" \\\\\n");
1118            format!(
1119                r"\operatorname{{{}}}\colon \begin{{aligned}}{}\end{{aligned}}",
1120                KNOW, rows
1121            )
1122        }
1123    }
1124}
1125
1126impl LessEqualFact {
1127    pub fn to_latex_string(&self) -> String {
1128        format!(
1129            r"{} \leq {}",
1130            self.left.to_latex_string(),
1131            self.right.to_latex_string()
1132        )
1133    }
1134}
1135
1136impl LessFact {
1137    pub fn to_latex_string(&self) -> String {
1138        format!(
1139            "{} < {}",
1140            self.left.to_latex_string(),
1141            self.right.to_latex_string()
1142        )
1143    }
1144}
1145
1146impl ListSet {
1147    pub fn to_latex_string(&self) -> String {
1148        let inner = self
1149            .list
1150            .iter()
1151            .map(|o| o.to_latex_string())
1152            .collect::<Vec<_>>()
1153            .join(", ");
1154        format!(r"\left\{{ {} \right\}}", inner)
1155    }
1156}
1157
1158impl Log {
1159    pub fn to_latex_string(&self) -> String {
1160        format!(
1161            r"\log_{{{}}} \left( {} \right)",
1162            self.base.to_latex_string(),
1163            self.arg.to_latex_string()
1164        )
1165    }
1166}
1167
1168impl MatrixAdd {
1169    pub fn to_latex_string(&self) -> String {
1170        format!(
1171            r"{} \mathbin{{\mathrm{{{}}}}} {}",
1172            self.left.to_latex_string(),
1173            latex_escape_underscore(MATRIX_ADD),
1174            self.right.to_latex_string()
1175        )
1176    }
1177}
1178
1179impl MatrixListObj {
1180    pub fn to_latex_string(&self) -> String {
1181        let rows = self
1182            .rows
1183            .iter()
1184            .map(|row| {
1185                let inner = row
1186                    .iter()
1187                    .map(|o| o.to_latex_string())
1188                    .collect::<Vec<_>>()
1189                    .join(", ");
1190                format!(r"\left( {} \right)", inner)
1191            })
1192            .collect::<Vec<_>>()
1193            .join(", ");
1194        format!(r"\left[ {} \right]", rows)
1195    }
1196}
1197
1198impl MatrixMul {
1199    pub fn to_latex_string(&self) -> String {
1200        format!(
1201            r"{} \mathbin{{\mathrm{{{}}}}} {}",
1202            self.left.to_latex_string(),
1203            latex_escape_underscore(MATRIX_MUL),
1204            self.right.to_latex_string()
1205        )
1206    }
1207}
1208
1209impl MatrixPow {
1210    pub fn to_latex_string(&self) -> String {
1211        format!(
1212            r"{} \mathbin{{\mathrm{{{}}}}} {}",
1213            self.base.to_latex_string(),
1214            latex_escape_underscore(MATRIX_POW),
1215            self.exponent.to_latex_string()
1216        )
1217    }
1218}
1219
1220impl MatrixScalarMul {
1221    pub fn to_latex_string(&self) -> String {
1222        format!(
1223            r"{} \mathbin{{\mathrm{{{}}}}} {}",
1224            self.scalar.to_latex_string(),
1225            latex_escape_underscore(MATRIX_SCALAR_MUL),
1226            self.matrix.to_latex_string()
1227        )
1228    }
1229}
1230
1231impl MatrixSet {
1232    pub fn to_latex_string(&self) -> String {
1233        format!(
1234            r"\operatorname{{{}}}\left( {}, {}, {} \right)",
1235            MATRIX,
1236            self.set.to_latex_string(),
1237            self.row_len.to_latex_string(),
1238            self.col_len.to_latex_string()
1239        )
1240    }
1241}
1242
1243impl MatrixSub {
1244    pub fn to_latex_string(&self) -> String {
1245        format!(
1246            r"{} \mathbin{{\mathrm{{{}}}}} {}",
1247            self.left.to_latex_string(),
1248            latex_escape_underscore(MATRIX_SUB),
1249            self.right.to_latex_string()
1250        )
1251    }
1252}
1253
1254impl Max {
1255    pub fn to_latex_string(&self) -> String {
1256        format!(
1257            r"\max \left( {}, {} \right)",
1258            self.left.to_latex_string(),
1259            self.right.to_latex_string()
1260        )
1261    }
1262}
1263
1264impl Min {
1265    pub fn to_latex_string(&self) -> String {
1266        format!(
1267            r"\min \left( {}, {} \right)",
1268            self.left.to_latex_string(),
1269            self.right.to_latex_string()
1270        )
1271    }
1272}
1273
1274impl Mod {
1275    pub fn to_latex_string(&self) -> String {
1276        format!(
1277            r"\left( {} \mathbin{{\mathrm{{mod}}}} {} \right)",
1278            self.left.to_latex_string(),
1279            self.right.to_latex_string()
1280        )
1281    }
1282}
1283
1284impl Mul {
1285    pub fn to_latex_string(&self) -> String {
1286        format!(
1287            r"{0} \cdot {1}",
1288            self.left.to_latex_string(),
1289            self.right.to_latex_string()
1290        )
1291    }
1292}
1293
1294impl NormalAtomicFact {
1295    pub fn to_latex_string(&self) -> String {
1296        let pred = self.predicate.to_latex_string();
1297        let args = self
1298            .body
1299            .iter()
1300            .map(|o| o.to_latex_string())
1301            .collect::<Vec<_>>()
1302            .join(", ");
1303        format!(r"\$ {}\left( {}\right)", pred, args)
1304    }
1305}
1306
1307impl NotEqualFact {
1308    pub fn to_latex_string(&self) -> String {
1309        format!(
1310            r"{} \neq {}",
1311            self.left.to_latex_string(),
1312            self.right.to_latex_string()
1313        )
1314    }
1315}
1316
1317impl NotGreaterEqualFact {
1318    pub fn to_latex_string(&self) -> String {
1319        format!(
1320            r"{} \ngeq {}",
1321            self.left.to_latex_string(),
1322            self.right.to_latex_string()
1323        )
1324    }
1325}
1326
1327impl NotGreaterFact {
1328    pub fn to_latex_string(&self) -> String {
1329        format!(
1330            r"{} \ngtr {}",
1331            self.left.to_latex_string(),
1332            self.right.to_latex_string()
1333        )
1334    }
1335}
1336
1337impl NotInFact {
1338    pub fn to_latex_string(&self) -> String {
1339        format!(
1340            r"{} \notin {}",
1341            self.element.to_latex_string(),
1342            self.set.to_latex_string()
1343        )
1344    }
1345}
1346
1347impl NotIsCartFact {
1348    pub fn to_latex_string(&self) -> String {
1349        format!(
1350            r"\neg \left( \$ \mathrm{{{}}}\left( {}\right) \right)",
1351            IS_CART,
1352            self.set.to_latex_string()
1353        )
1354    }
1355}
1356
1357impl NotIsFiniteSetFact {
1358    pub fn to_latex_string(&self) -> String {
1359        format!(
1360            r"\neg \left( \$ \mathrm{{{}}}\left( {}\right) \right)",
1361            IS_FINITE_SET,
1362            self.set.to_latex_string()
1363        )
1364    }
1365}
1366
1367impl NotIsNonemptySetFact {
1368    pub fn to_latex_string(&self) -> String {
1369        format!(
1370            r"\neg \left( \$ \mathrm{{{}}}\left( {}\right) \right)",
1371            IS_NONEMPTY_SET,
1372            self.set.to_latex_string()
1373        )
1374    }
1375}
1376
1377impl NotIsSetFact {
1378    pub fn to_latex_string(&self) -> String {
1379        format!(
1380            r"\neg \left( \$ \mathrm{{{}}}\left( {}\right) \right)",
1381            IS_SET,
1382            self.set.to_latex_string()
1383        )
1384    }
1385}
1386
1387impl NotIsTupleFact {
1388    pub fn to_latex_string(&self) -> String {
1389        format!(
1390            r"\neg \left( \$ \mathrm{{{}}}\left( {}\right) \right)",
1391            IS_TUPLE,
1392            self.set.to_latex_string()
1393        )
1394    }
1395}
1396
1397impl NotLessEqualFact {
1398    pub fn to_latex_string(&self) -> String {
1399        format!(
1400            r"{} \nleq {}",
1401            self.left.to_latex_string(),
1402            self.right.to_latex_string()
1403        )
1404    }
1405}
1406
1407impl NotLessFact {
1408    pub fn to_latex_string(&self) -> String {
1409        format!(
1410            r"{} \nless {}",
1411            self.left.to_latex_string(),
1412            self.right.to_latex_string()
1413        )
1414    }
1415}
1416
1417impl NotNormalAtomicFact {
1418    pub fn to_latex_string(&self) -> String {
1419        let pred = self.predicate.to_latex_string();
1420        let args = self
1421            .body
1422            .iter()
1423            .map(|o| o.to_latex_string())
1424            .collect::<Vec<_>>()
1425            .join(", ");
1426        format!(r"\neg \left( \$ {}\left( {}\right) \right)", pred, args)
1427    }
1428}
1429
1430impl NotRestrictFact {
1431    pub fn to_latex_string(&self) -> String {
1432        format!(
1433            r"\neg \left( {} \mathrel{{\$}} \mathrm{{{}}}\, {} \right)",
1434            self.obj.to_latex_string(),
1435            RESTRICT_FN_IN,
1436            self.obj_cannot_restrict_to_fn_set.to_latex_string()
1437        )
1438    }
1439}
1440
1441impl NotSubsetFact {
1442    pub fn to_latex_string(&self) -> String {
1443        format!(
1444            r"\neg \left( {} \subseteq {} \right)",
1445            self.left.to_latex_string(),
1446            self.right.to_latex_string()
1447        )
1448    }
1449}
1450
1451impl NotSupersetFact {
1452    pub fn to_latex_string(&self) -> String {
1453        format!(
1454            r"\neg \left( {} \supseteq {} \right)",
1455            self.left.to_latex_string(),
1456            self.right.to_latex_string()
1457        )
1458    }
1459}
1460
1461impl Number {
1462    pub fn to_latex_string(&self) -> String {
1463        self.normalized_value.clone()
1464    }
1465}
1466
1467impl ObjAtIndex {
1468    pub fn to_latex_string(&self) -> String {
1469        format!(
1470            r"{}\left[ {} \right]",
1471            self.obj.to_latex_string(),
1472            self.index.to_latex_string()
1473        )
1474    }
1475}
1476
1477impl OrFact {
1478    pub fn to_latex_string(&self) -> String {
1479        self.facts
1480            .iter()
1481            .map(|f| f.to_latex_string())
1482            .collect::<Vec<_>>()
1483            .join(r" \lor ")
1484    }
1485}
1486
1487impl ParamDefWithType {
1488    pub fn to_latex_string(&self) -> String {
1489        self.groups
1490            .iter()
1491            .map(|g| g.to_latex_string())
1492            .collect::<Vec<_>>()
1493            .join(", ")
1494    }
1495}
1496
1497impl ParamGroupWithParamType {
1498    pub fn to_latex_string(&self) -> String {
1499        let names = self
1500            .params
1501            .iter()
1502            .map(|p| latex_local_ident(p))
1503            .collect::<Vec<_>>()
1504            .join(", ");
1505        format!(r"{}, {}", names, self.param_type.to_latex_string())
1506    }
1507}
1508
1509impl ParamType {
1510    pub fn to_latex_string(&self) -> String {
1511        match self {
1512            ParamType::Set(_) => format!(r"\mathrm{{{}}}", SET),
1513            ParamType::NonemptySet(_) => format!(r"\mathrm{{{}}}", NONEMPTY_SET),
1514            ParamType::FiniteSet(_) => format!(r"\mathrm{{{}}}", FINITE_SET),
1515            ParamType::Restrictive(fs) => format!(
1516                r"\mathrm{{{}}} {}{}{}",
1517                RESTRICTIVE,
1518                "(",
1519                Obj::FnSet(fs.clone()).to_latex_string(),
1520                ")"
1521            ),
1522            ParamType::Obj(o) => o.to_latex_string(),
1523        }
1524    }
1525}
1526
1527impl Pow {
1528    pub fn to_latex_string(&self) -> String {
1529        format!(
1530            "{{{}}}^{{{}}}",
1531            self.base.to_latex_string(),
1532            self.exponent.to_latex_string()
1533        )
1534    }
1535}
1536
1537impl PowerSet {
1538    pub fn to_latex_string(&self) -> String {
1539        format!(r"\mathcal{{P}}\left( {}\right)", self.set.to_latex_string())
1540    }
1541}
1542
1543impl Proj {
1544    pub fn to_latex_string(&self) -> String {
1545        format!(
1546            r"\operatorname{{{}}}\left( {}, {} \right)",
1547            PROJ,
1548            self.set.to_latex_string(),
1549            self.dim.to_latex_string()
1550        )
1551    }
1552}
1553
1554impl ProveStmt {
1555    pub fn to_latex_string(&self) -> String {
1556        if self.proof.is_empty() {
1557            return r"\text{\texttt{(empty proof)}}".to_string();
1558        }
1559        let rows: Vec<String> = self
1560            .proof
1561            .iter()
1562            .map(|st| format!(r"& \quad {}", st.to_latex_string()))
1563            .collect();
1564        format!(
1565            "\\begin{{aligned}}\n{}\n\\end{{aligned}}",
1566            rows.join(" \\\\\n")
1567        )
1568    }
1569}
1570
1571impl Range {
1572    pub fn to_latex_string(&self) -> String {
1573        format!(
1574            r"\operatorname{{{}}}\left( {}, {} \right)",
1575            RANGE,
1576            self.start.to_latex_string(),
1577            self.end.to_latex_string()
1578        )
1579    }
1580}
1581
1582impl RestrictFact {
1583    pub fn to_latex_string(&self) -> String {
1584        format!(
1585            r"{} \mathrel{{\$}} \mathrm{{{}}}\, {}",
1586            self.obj.to_latex_string(),
1587            RESTRICT_FN_IN,
1588            self.obj_can_restrict_to_fn_set.to_latex_string()
1589        )
1590    }
1591}
1592
1593impl RunFileStmt {
1594    pub fn to_latex_string(&self) -> String {
1595        format!(
1596            r"\operatorname{{{}}}\ \texttt{{{}}}",
1597            RUN_FILE,
1598            latex_texttt_escape(&self.file_path)
1599        )
1600    }
1601}
1602
1603impl SeqSet {
1604    pub fn to_latex_string(&self) -> String {
1605        format!(
1606            r"\operatorname{{{}}}\left( {}\right)",
1607            SEQ,
1608            self.set.to_latex_string()
1609        )
1610    }
1611}
1612
1613impl SetBuilder {
1614    pub fn to_latex_string(&self) -> String {
1615        let cond = self
1616            .facts
1617            .iter()
1618            .map(|f| f.to_latex_string())
1619            .collect::<Vec<_>>()
1620            .join(r" \land ");
1621        format!(
1622            r"\left\{{ {} \in {} \,\middle|\, {} \right\}}",
1623            latex_local_ident(&self.param),
1624            self.param_set.to_latex_string(),
1625            cond
1626        )
1627    }
1628}
1629
1630impl SetDiff {
1631    pub fn to_latex_string(&self) -> String {
1632        format!(
1633            r"\operatorname{{{}}}\left( {}, {} \right)",
1634            SET_DIFF,
1635            self.left.to_latex_string(),
1636            self.right.to_latex_string()
1637        )
1638    }
1639}
1640
1641impl SetMinus {
1642    pub fn to_latex_string(&self) -> String {
1643        format!(
1644            r"{} \setminus {}",
1645            self.left.to_latex_string(),
1646            self.right.to_latex_string()
1647        )
1648    }
1649}
1650
1651impl Sub {
1652    pub fn to_latex_string(&self) -> String {
1653        format!(
1654            "{} - {}",
1655            self.left.to_latex_string(),
1656            self.right.to_latex_string()
1657        )
1658    }
1659}
1660
1661impl SubsetFact {
1662    pub fn to_latex_string(&self) -> String {
1663        format!(
1664            r"{} \subseteq {}",
1665            self.left.to_latex_string(),
1666            self.right.to_latex_string()
1667        )
1668    }
1669}
1670
1671impl SupersetFact {
1672    pub fn to_latex_string(&self) -> String {
1673        format!(
1674            r"{} \supseteq {}",
1675            self.left.to_latex_string(),
1676            self.right.to_latex_string()
1677        )
1678    }
1679}
1680
1681impl Tuple {
1682    pub fn to_latex_string(&self) -> String {
1683        let inner = self
1684            .args
1685            .iter()
1686            .map(|o| o.to_latex_string())
1687            .collect::<Vec<_>>()
1688            .join(", ");
1689        format!(r"\left( {} \right)", inner)
1690    }
1691}
1692
1693impl TupleDim {
1694    pub fn to_latex_string(&self) -> String {
1695        format!(
1696            r"\operatorname{{{}}}\left( {}\right)",
1697            TUPLE_DIM,
1698            self.arg.to_latex_string()
1699        )
1700    }
1701}
1702
1703impl Union {
1704    pub fn to_latex_string(&self) -> String {
1705        format!(
1706            r"{} \cup {}",
1707            self.left.to_latex_string(),
1708            self.right.to_latex_string()
1709        )
1710    }
1711}
1712
1713impl WitnessExistFact {
1714    pub fn to_latex_string(&self) -> String {
1715        let names = self
1716            .equal_tos
1717            .iter()
1718            .map(|o| o.to_latex_string())
1719            .collect::<Vec<_>>()
1720            .join(", ");
1721        let facts = self
1722            .exist_fact_in_witness
1723            .facts()
1724            .iter()
1725            .map(|f| f.to_latex_string())
1726            .collect::<Vec<_>>()
1727            .join(", ");
1728        let head = format!(
1729            r"\mathrm{{witness}}\ {} : {} \mathrm{{st}} \left\{{ {}\right\}}",
1730            names,
1731            self.exist_fact_in_witness
1732                .params_def_with_type()
1733                .to_latex_string(),
1734            facts
1735        );
1736        if self.proof.is_empty() {
1737            head
1738        } else {
1739            let mut rows = vec![format!(r"{} &", head)];
1740            for st in &self.proof {
1741                rows.push(format!(r"& \quad {}", st.to_latex_string()));
1742            }
1743            format!(
1744                "\\begin{{aligned}}\n{}\n\\end{{aligned}}",
1745                rows.join(" \\\\\n")
1746            )
1747        }
1748    }
1749}
1750
1751impl WitnessNonemptySet {
1752    pub fn to_latex_string(&self) -> String {
1753        let head = format!(
1754            r"\mathrm{{witness}}\ {} {}",
1755            self.obj.to_latex_string(),
1756            self.set.to_latex_string()
1757        );
1758        if self.proof.is_empty() {
1759            head
1760        } else {
1761            let mut rows = vec![format!(r"{} &", head)];
1762            for st in &self.proof {
1763                rows.push(format!(r"& \quad {}", st.to_latex_string()));
1764            }
1765            format!(
1766                "\\begin{{aligned}}\n{}\n\\end{{aligned}}",
1767                rows.join(" \\\\\n")
1768            )
1769        }
1770    }
1771}
1772
1773impl ImportGlobalModuleStmt {
1774    pub fn to_latex_string(&self) -> String {
1775        match &self.as_mod_name {
1776            Some(m) => format!(
1777                r"\operatorname{{{}}}\ {}\ \mathrm{{as}}\ {}",
1778                IMPORT,
1779                latex_local_ident(&self.mod_name),
1780                latex_local_ident(m)
1781            ),
1782            None => format!(
1783                r"\operatorname{{{}}}\ {}",
1784                IMPORT,
1785                latex_local_ident(&self.mod_name)
1786            ),
1787        }
1788    }
1789}
1790
1791impl ImportRelativePathStmt {
1792    pub fn to_latex_string(&self) -> String {
1793        let path = latex_texttt_escape(&self.path);
1794        match &self.as_mod_name {
1795            Some(m) => format!(
1796                r"\operatorname{{{}}}\ \texttt{{{}}}\ \mathrm{{as}}\ {}",
1797                IMPORT,
1798                path,
1799                latex_local_ident(m)
1800            ),
1801            None => format!(r"\operatorname{{{}}}\ \texttt{{{}}}", IMPORT, path),
1802        }
1803    }
1804}
1805
1806impl ImportStmt {
1807    pub fn to_latex_string(&self) -> String {
1808        match self {
1809            ImportStmt::ImportRelativePath(s) => s.to_latex_string(),
1810            ImportStmt::ImportGlobalModule(s) => s.to_latex_string(),
1811        }
1812    }
1813}
1814
1815impl StandardSet {
1816    pub fn to_latex_string(&self) -> String {
1817        match self {
1818            StandardSet::N => r"\mathbb{N}".to_string(),
1819            StandardSet::NPos => r"\mathbb{N}_{>0}".to_string(),
1820            StandardSet::Z => r"\mathbb{Z}".to_string(),
1821            StandardSet::ZNeg => r"\mathbb{Z}_{<0}".to_string(),
1822            StandardSet::ZNz => r"\mathbb{Z}\setminus\{0\}".to_string(),
1823            StandardSet::Q => r"\mathbb{Q}".to_string(),
1824            StandardSet::QPos => r"\mathbb{Q}_{>0}".to_string(),
1825            StandardSet::QNeg => r"\mathbb{Q}_{<0}".to_string(),
1826            StandardSet::QNz => r"\mathbb{Q}\setminus\{0\}".to_string(),
1827            StandardSet::R => r"\mathbb{R}".to_string(),
1828            StandardSet::RPos => r"\mathbb{R}_{>0}".to_string(),
1829            StandardSet::RNeg => r"\mathbb{R}_{<0}".to_string(),
1830            StandardSet::RNz => r"\mathbb{R}\setminus\{0\}".to_string(),
1831        }
1832    }
1833}
1834
1835impl Fact {
1836    pub fn to_latex_string(&self) -> String {
1837        match self {
1838            Fact::AtomicFact(x) => x.to_latex_string(),
1839            Fact::ExistFact(x) => x.to_latex_string(),
1840            Fact::OrFact(x) => x.to_latex_string(),
1841            Fact::AndFact(x) => x.to_latex_string(),
1842            Fact::ChainFact(x) => x.to_latex_string(),
1843            Fact::ForallFact(x) => x.to_latex_string(),
1844            Fact::ForallFactWithIff(x) => x.to_latex_string(),
1845            Fact::NotForall(x) => x.to_latex_string(),
1846        }
1847    }
1848}
1849
1850impl AtomicFact {
1851    pub fn to_latex_string(&self) -> String {
1852        match self {
1853            AtomicFact::NormalAtomicFact(x) => x.to_latex_string(),
1854            AtomicFact::EqualFact(x) => x.to_latex_string(),
1855            AtomicFact::LessFact(x) => x.to_latex_string(),
1856            AtomicFact::GreaterFact(x) => x.to_latex_string(),
1857            AtomicFact::LessEqualFact(x) => x.to_latex_string(),
1858            AtomicFact::GreaterEqualFact(x) => x.to_latex_string(),
1859            AtomicFact::IsSetFact(x) => x.to_latex_string(),
1860            AtomicFact::IsNonemptySetFact(x) => x.to_latex_string(),
1861            AtomicFact::IsFiniteSetFact(x) => x.to_latex_string(),
1862            AtomicFact::InFact(x) => x.to_latex_string(),
1863            AtomicFact::IsCartFact(x) => x.to_latex_string(),
1864            AtomicFact::IsTupleFact(x) => x.to_latex_string(),
1865            AtomicFact::SubsetFact(x) => x.to_latex_string(),
1866            AtomicFact::SupersetFact(x) => x.to_latex_string(),
1867            AtomicFact::RestrictFact(x) => x.to_latex_string(),
1868            AtomicFact::NotRestrictFact(x) => x.to_latex_string(),
1869            AtomicFact::NotNormalAtomicFact(x) => x.to_latex_string(),
1870            AtomicFact::NotEqualFact(x) => x.to_latex_string(),
1871            AtomicFact::NotLessFact(x) => x.to_latex_string(),
1872            AtomicFact::NotGreaterFact(x) => x.to_latex_string(),
1873            AtomicFact::NotLessEqualFact(x) => x.to_latex_string(),
1874            AtomicFact::NotGreaterEqualFact(x) => x.to_latex_string(),
1875            AtomicFact::NotIsSetFact(x) => x.to_latex_string(),
1876            AtomicFact::NotIsNonemptySetFact(x) => x.to_latex_string(),
1877            AtomicFact::NotIsFiniteSetFact(x) => x.to_latex_string(),
1878            AtomicFact::NotInFact(x) => x.to_latex_string(),
1879            AtomicFact::NotIsCartFact(x) => x.to_latex_string(),
1880            AtomicFact::NotIsTupleFact(x) => x.to_latex_string(),
1881            AtomicFact::NotSubsetFact(x) => x.to_latex_string(),
1882            AtomicFact::NotSupersetFact(x) => x.to_latex_string(),
1883            AtomicFact::FnEqualInFact(f) => format!(
1884                r"\mathsf{{fn\_eq\_in}}({},{},{})",
1885                f.left.to_latex_string(),
1886                f.right.to_latex_string(),
1887                f.set.to_latex_string(),
1888            ),
1889            AtomicFact::FnEqualFact(f) => format!(
1890                r"\mathsf{{fn\_eq}}({},{})",
1891                f.left.to_latex_string(),
1892                f.right.to_latex_string(),
1893            ),
1894        }
1895    }
1896}
1897
1898impl Obj {
1899    pub fn to_latex_string(&self) -> String {
1900        match self {
1901            Obj::Atom(AtomObj::Identifier(x)) => x.to_latex_string(),
1902            Obj::Atom(AtomObj::IdentifierWithMod(x)) => x.to_latex_string(),
1903            Obj::FnObj(x) => x.to_latex_string(),
1904            Obj::Number(x) => x.to_latex_string(),
1905            Obj::Add(x) => x.to_latex_string(),
1906            Obj::Sub(x) => x.to_latex_string(),
1907            Obj::Mul(x) => x.to_latex_string(),
1908            Obj::Div(x) => x.to_latex_string(),
1909            Obj::Mod(x) => x.to_latex_string(),
1910            Obj::Pow(x) => x.to_latex_string(),
1911            Obj::Abs(x) => x.to_latex_string(),
1912            Obj::Log(x) => x.to_latex_string(),
1913            Obj::Max(x) => x.to_latex_string(),
1914            Obj::Min(x) => x.to_latex_string(),
1915            Obj::Union(x) => x.to_latex_string(),
1916            Obj::Intersect(x) => x.to_latex_string(),
1917            Obj::SetMinus(x) => x.to_latex_string(),
1918            Obj::SetDiff(x) => x.to_latex_string(),
1919            Obj::Cup(x) => x.to_latex_string(),
1920            Obj::Cap(x) => x.to_latex_string(),
1921            Obj::PowerSet(x) => x.to_latex_string(),
1922            Obj::ListSet(x) => x.to_latex_string(),
1923            Obj::SetBuilder(x) => x.to_latex_string(),
1924            Obj::FnSet(x) => x.to_latex_string(),
1925            Obj::AnonymousFn(x) => x.to_latex_string(),
1926            Obj::Cart(x) => x.to_latex_string(),
1927            Obj::CartDim(x) => x.to_latex_string(),
1928            Obj::Proj(x) => x.to_latex_string(),
1929            Obj::TupleDim(x) => x.to_latex_string(),
1930            Obj::Tuple(x) => x.to_latex_string(),
1931            Obj::Count(x) => x.to_latex_string(),
1932            Obj::Sum(x) => x.to_latex_string(),
1933            Obj::Product(x) => x.to_latex_string(),
1934            Obj::Range(x) => x.to_latex_string(),
1935            Obj::ClosedRange(x) => x.to_latex_string(),
1936            Obj::FiniteSeqSet(x) => x.to_latex_string(),
1937            Obj::SeqSet(x) => x.to_latex_string(),
1938            Obj::FiniteSeqListObj(x) => x.to_latex_string(),
1939            Obj::Choose(x) => x.to_latex_string(),
1940            Obj::ObjAtIndex(x) => x.to_latex_string(),
1941            Obj::StandardSet(x) => x.to_latex_string(),
1942            Obj::FamilyObj(x) => x.to_latex_string(),
1943            Obj::Atom(AtomObj::Forall(x)) => latex_local_ident(&x.name),
1944            Obj::Atom(AtomObj::Def(x)) => latex_local_ident(&x.name),
1945            Obj::Atom(AtomObj::Exist(x)) => latex_local_ident(&x.name),
1946            Obj::Atom(AtomObj::SetBuilder(x)) => latex_local_ident(&x.name),
1947            Obj::Atom(AtomObj::FnSet(x)) => latex_local_ident(&x.name),
1948            Obj::Atom(AtomObj::Induc(x)) => latex_local_ident(&x.name),
1949            Obj::Atom(AtomObj::DefAlgo(x)) => latex_local_ident(&x.name),
1950            Obj::MatrixSet(x) => x.to_latex_string(),
1951            Obj::MatrixListObj(x) => x.to_latex_string(),
1952            Obj::MatrixAdd(x) => x.to_latex_string(),
1953            Obj::MatrixSub(x) => x.to_latex_string(),
1954            Obj::MatrixMul(x) => x.to_latex_string(),
1955            Obj::MatrixScalarMul(x) => x.to_latex_string(),
1956            Obj::MatrixPow(x) => x.to_latex_string(),
1957        }
1958    }
1959}
1960
1961impl Stmt {
1962    pub fn to_latex_string(&self) -> String {
1963        match self {
1964            Stmt::Fact(x) => x.to_latex_string(),
1965            Stmt::DefLetStmt(x) => x.to_latex_string(),
1966            Stmt::DefPropStmt(x) => x.to_latex_string(),
1967            Stmt::DefAbstractPropStmt(x) => x.to_latex_string(),
1968            Stmt::HaveObjInNonemptySetStmt(x) => x.to_latex_string(),
1969            Stmt::HaveObjEqualStmt(x) => x.to_latex_string(),
1970            Stmt::HaveByExistStmt(x) => x.to_latex_string(),
1971            Stmt::HaveFnEqualStmt(x) => x.to_latex_string(),
1972            Stmt::HaveFnEqualCaseByCaseStmt(x) => x.to_latex_string(),
1973            Stmt::HaveFnByInducStmt(x) => x.to_latex_string(),
1974            Stmt::DefFamilyStmt(x) => x.to_latex_string(),
1975            Stmt::DefAlgoStmt(x) => x.to_latex_string(),
1976            Stmt::ClaimStmt(x) => x.to_latex_string(),
1977            Stmt::KnowStmt(x) => x.to_latex_string(),
1978            Stmt::ProveStmt(x) => x.to_latex_string(),
1979            Stmt::ImportStmt(x) => x.to_latex_string(),
1980            Stmt::DoNothingStmt(x) => x.to_latex_string(),
1981            Stmt::ClearStmt(x) => x.to_latex_string(),
1982            Stmt::RunFileStmt(x) => x.to_latex_string(),
1983            Stmt::EvalStmt(x) => x.to_latex_string(),
1984            Stmt::WitnessExistFact(x) => x.to_latex_string(),
1985            Stmt::WitnessNonemptySet(x) => x.to_latex_string(),
1986            Stmt::ByCasesStmt(x) => x.to_latex_string(),
1987            Stmt::ByContraStmt(x) => x.to_latex_string(),
1988            Stmt::ByEnumerateFiniteSetStmt(x) => x.to_latex_string(),
1989            Stmt::ByInducStmt(x) => x.to_latex_string(),
1990            Stmt::ByForStmt(x) => x.to_latex_string(),
1991            Stmt::ByExtensionStmt(x) => x.to_latex_string(),
1992            Stmt::ByFnStmt(x) => x.to_latex_string(),
1993            Stmt::ByFamilyStmt(x) => x.to_latex_string(),
1994            Stmt::ByTuple(x) => x.to_latex_string(),
1995            Stmt::ByFnSetStmt(x) => x.to_latex_string(),
1996            Stmt::ByEnumerateClosedRangeStmt(x) => x.to_latex_string(),
1997        }
1998    }
1999}