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}