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 format!(
969 r"\mathrm{{have}}\ \mathrm{{fn}}\ {}\ {} {}",
970 latex_local_ident(&self.name),
971 fn_set_clause_latex(&self.fn_set_clause),
972 self.equal_to.to_latex_string()
973 )
974 }
975}
976
977impl HaveObjEqualStmt {
978 pub fn to_latex_string(&self) -> String {
979 let rhs = self
980 .objs_equal_to
981 .iter()
982 .map(|o| o.to_latex_string())
983 .collect::<Vec<_>>()
984 .join(", ");
985 format!(
986 r"\mathrm{{have}}\ {} = {}",
987 self.param_def.to_latex_string(),
988 rhs
989 )
990 }
991}
992
993impl HaveObjInNonemptySetOrParamTypeStmt {
994 pub fn to_latex_string(&self) -> String {
995 format!(r"\mathrm{{have}}\ {}", self.param_def.to_latex_string())
996 }
997}
998
999impl Identifier {
1000 pub fn to_latex_string(&self) -> String {
1001 latex_local_ident(&self.name)
1002 }
1003}
1004
1005impl IdentifierWithMod {
1006 pub fn to_latex_string(&self) -> String {
1007 format!(
1008 r"{}\mathbin{{\mathrm{{::}}}}{}",
1009 latex_local_ident(&self.mod_name),
1010 latex_local_ident(&self.name)
1011 )
1012 }
1013}
1014
1015impl AtomicName {
1016 pub fn to_latex_string(&self) -> String {
1017 match self {
1018 AtomicName::WithoutMod(s) => latex_local_ident(s),
1019 AtomicName::WithMod(m, n) => format!(
1020 r"{}\mathbin{{\mathrm{{::}}}}{}",
1021 latex_local_ident(m),
1022 latex_local_ident(n)
1023 ),
1024 }
1025 }
1026}
1027
1028impl InFact {
1029 pub fn to_latex_string(&self) -> String {
1030 format!(
1031 r"{} \in {}",
1032 self.element.to_latex_string(),
1033 self.set.to_latex_string()
1034 )
1035 }
1036}
1037
1038impl Intersect {
1039 pub fn to_latex_string(&self) -> String {
1040 format!(
1041 r"{} \cap {}",
1042 self.left.to_latex_string(),
1043 self.right.to_latex_string()
1044 )
1045 }
1046}
1047
1048impl IsCartFact {
1049 pub fn to_latex_string(&self) -> String {
1050 format!(
1051 r"\$ \mathrm{{{}}}\left( {}\right)",
1052 IS_CART,
1053 self.set.to_latex_string()
1054 )
1055 }
1056}
1057
1058impl IsFiniteSetFact {
1059 pub fn to_latex_string(&self) -> String {
1060 format!(
1061 r"\$ \mathrm{{{}}}\left( {}\right)",
1062 IS_FINITE_SET,
1063 self.set.to_latex_string()
1064 )
1065 }
1066}
1067
1068impl IsNonemptySetFact {
1069 pub fn to_latex_string(&self) -> String {
1070 format!(
1071 r"\$ \mathrm{{{}}}\left( {}\right)",
1072 IS_NONEMPTY_SET,
1073 self.set.to_latex_string()
1074 )
1075 }
1076}
1077
1078impl IsSetFact {
1079 pub fn to_latex_string(&self) -> String {
1080 format!(
1081 r"\$ \mathrm{{{}}}\left( {}\right)",
1082 IS_SET,
1083 self.set.to_latex_string()
1084 )
1085 }
1086}
1087
1088impl IsTupleFact {
1089 pub fn to_latex_string(&self) -> String {
1090 format!(
1091 r"\$ \mathrm{{{}}}\left( {}\right)",
1092 IS_TUPLE,
1093 self.set.to_latex_string()
1094 )
1095 }
1096}
1097
1098impl KnowStmt {
1099 pub fn to_latex_string(&self) -> String {
1100 if self.facts.len() == 1 {
1101 format!(
1102 r"\operatorname{{{}}} {}",
1103 KNOW,
1104 self.facts[0].to_latex_string()
1105 )
1106 } else {
1107 let rows = self
1108 .facts
1109 .iter()
1110 .map(|fact| format!("& {}", fact.to_latex_string()))
1111 .collect::<Vec<_>>()
1112 .join(" \\\\\n");
1113 format!(
1114 r"\operatorname{{{}}}\colon \begin{{aligned}}{}\end{{aligned}}",
1115 KNOW, rows
1116 )
1117 }
1118 }
1119}
1120
1121impl LessEqualFact {
1122 pub fn to_latex_string(&self) -> String {
1123 format!(
1124 r"{} \leq {}",
1125 self.left.to_latex_string(),
1126 self.right.to_latex_string()
1127 )
1128 }
1129}
1130
1131impl LessFact {
1132 pub fn to_latex_string(&self) -> String {
1133 format!(
1134 "{} < {}",
1135 self.left.to_latex_string(),
1136 self.right.to_latex_string()
1137 )
1138 }
1139}
1140
1141impl ListSet {
1142 pub fn to_latex_string(&self) -> String {
1143 let inner = self
1144 .list
1145 .iter()
1146 .map(|o| o.to_latex_string())
1147 .collect::<Vec<_>>()
1148 .join(", ");
1149 format!(r"\left\{{ {} \right\}}", inner)
1150 }
1151}
1152
1153impl Log {
1154 pub fn to_latex_string(&self) -> String {
1155 format!(
1156 r"\log_{{{}}} \left( {} \right)",
1157 self.base.to_latex_string(),
1158 self.arg.to_latex_string()
1159 )
1160 }
1161}
1162
1163impl MatrixAdd {
1164 pub fn to_latex_string(&self) -> String {
1165 format!(
1166 r"{} \mathbin{{\mathrm{{{}}}}} {}",
1167 self.left.to_latex_string(),
1168 latex_escape_underscore(MATRIX_ADD),
1169 self.right.to_latex_string()
1170 )
1171 }
1172}
1173
1174impl MatrixListObj {
1175 pub fn to_latex_string(&self) -> String {
1176 let rows = self
1177 .rows
1178 .iter()
1179 .map(|row| {
1180 let inner = row
1181 .iter()
1182 .map(|o| o.to_latex_string())
1183 .collect::<Vec<_>>()
1184 .join(", ");
1185 format!(r"\left( {} \right)", inner)
1186 })
1187 .collect::<Vec<_>>()
1188 .join(", ");
1189 format!(r"\left[ {} \right]", rows)
1190 }
1191}
1192
1193impl MatrixMul {
1194 pub fn to_latex_string(&self) -> String {
1195 format!(
1196 r"{} \mathbin{{\mathrm{{{}}}}} {}",
1197 self.left.to_latex_string(),
1198 latex_escape_underscore(MATRIX_MUL),
1199 self.right.to_latex_string()
1200 )
1201 }
1202}
1203
1204impl MatrixPow {
1205 pub fn to_latex_string(&self) -> String {
1206 format!(
1207 r"{} \mathbin{{\mathrm{{{}}}}} {}",
1208 self.base.to_latex_string(),
1209 latex_escape_underscore(MATRIX_POW),
1210 self.exponent.to_latex_string()
1211 )
1212 }
1213}
1214
1215impl MatrixScalarMul {
1216 pub fn to_latex_string(&self) -> String {
1217 format!(
1218 r"{} \mathbin{{\mathrm{{{}}}}} {}",
1219 self.scalar.to_latex_string(),
1220 latex_escape_underscore(MATRIX_SCALAR_MUL),
1221 self.matrix.to_latex_string()
1222 )
1223 }
1224}
1225
1226impl MatrixSet {
1227 pub fn to_latex_string(&self) -> String {
1228 format!(
1229 r"\operatorname{{{}}}\left( {}, {}, {} \right)",
1230 MATRIX,
1231 self.set.to_latex_string(),
1232 self.row_len.to_latex_string(),
1233 self.col_len.to_latex_string()
1234 )
1235 }
1236}
1237
1238impl MatrixSub {
1239 pub fn to_latex_string(&self) -> String {
1240 format!(
1241 r"{} \mathbin{{\mathrm{{{}}}}} {}",
1242 self.left.to_latex_string(),
1243 latex_escape_underscore(MATRIX_SUB),
1244 self.right.to_latex_string()
1245 )
1246 }
1247}
1248
1249impl Max {
1250 pub fn to_latex_string(&self) -> String {
1251 format!(
1252 r"\max \left( {}, {} \right)",
1253 self.left.to_latex_string(),
1254 self.right.to_latex_string()
1255 )
1256 }
1257}
1258
1259impl Min {
1260 pub fn to_latex_string(&self) -> String {
1261 format!(
1262 r"\min \left( {}, {} \right)",
1263 self.left.to_latex_string(),
1264 self.right.to_latex_string()
1265 )
1266 }
1267}
1268
1269impl Mod {
1270 pub fn to_latex_string(&self) -> String {
1271 format!(
1272 r"\left( {} \mathbin{{\mathrm{{mod}}}} {} \right)",
1273 self.left.to_latex_string(),
1274 self.right.to_latex_string()
1275 )
1276 }
1277}
1278
1279impl Mul {
1280 pub fn to_latex_string(&self) -> String {
1281 format!(
1282 r"{0} \cdot {1}",
1283 self.left.to_latex_string(),
1284 self.right.to_latex_string()
1285 )
1286 }
1287}
1288
1289impl NormalAtomicFact {
1290 pub fn to_latex_string(&self) -> String {
1291 let pred = self.predicate.to_latex_string();
1292 let args = self
1293 .body
1294 .iter()
1295 .map(|o| o.to_latex_string())
1296 .collect::<Vec<_>>()
1297 .join(", ");
1298 format!(r"\$ {}\left( {}\right)", pred, args)
1299 }
1300}
1301
1302impl NotEqualFact {
1303 pub fn to_latex_string(&self) -> String {
1304 format!(
1305 r"{} \neq {}",
1306 self.left.to_latex_string(),
1307 self.right.to_latex_string()
1308 )
1309 }
1310}
1311
1312impl NotGreaterEqualFact {
1313 pub fn to_latex_string(&self) -> String {
1314 format!(
1315 r"{} \ngeq {}",
1316 self.left.to_latex_string(),
1317 self.right.to_latex_string()
1318 )
1319 }
1320}
1321
1322impl NotGreaterFact {
1323 pub fn to_latex_string(&self) -> String {
1324 format!(
1325 r"{} \ngtr {}",
1326 self.left.to_latex_string(),
1327 self.right.to_latex_string()
1328 )
1329 }
1330}
1331
1332impl NotInFact {
1333 pub fn to_latex_string(&self) -> String {
1334 format!(
1335 r"{} \notin {}",
1336 self.element.to_latex_string(),
1337 self.set.to_latex_string()
1338 )
1339 }
1340}
1341
1342impl NotIsCartFact {
1343 pub fn to_latex_string(&self) -> String {
1344 format!(
1345 r"\neg \left( \$ \mathrm{{{}}}\left( {}\right) \right)",
1346 IS_CART,
1347 self.set.to_latex_string()
1348 )
1349 }
1350}
1351
1352impl NotIsFiniteSetFact {
1353 pub fn to_latex_string(&self) -> String {
1354 format!(
1355 r"\neg \left( \$ \mathrm{{{}}}\left( {}\right) \right)",
1356 IS_FINITE_SET,
1357 self.set.to_latex_string()
1358 )
1359 }
1360}
1361
1362impl NotIsNonemptySetFact {
1363 pub fn to_latex_string(&self) -> String {
1364 format!(
1365 r"\neg \left( \$ \mathrm{{{}}}\left( {}\right) \right)",
1366 IS_NONEMPTY_SET,
1367 self.set.to_latex_string()
1368 )
1369 }
1370}
1371
1372impl NotIsSetFact {
1373 pub fn to_latex_string(&self) -> String {
1374 format!(
1375 r"\neg \left( \$ \mathrm{{{}}}\left( {}\right) \right)",
1376 IS_SET,
1377 self.set.to_latex_string()
1378 )
1379 }
1380}
1381
1382impl NotIsTupleFact {
1383 pub fn to_latex_string(&self) -> String {
1384 format!(
1385 r"\neg \left( \$ \mathrm{{{}}}\left( {}\right) \right)",
1386 IS_TUPLE,
1387 self.set.to_latex_string()
1388 )
1389 }
1390}
1391
1392impl NotLessEqualFact {
1393 pub fn to_latex_string(&self) -> String {
1394 format!(
1395 r"{} \nleq {}",
1396 self.left.to_latex_string(),
1397 self.right.to_latex_string()
1398 )
1399 }
1400}
1401
1402impl NotLessFact {
1403 pub fn to_latex_string(&self) -> String {
1404 format!(
1405 r"{} \nless {}",
1406 self.left.to_latex_string(),
1407 self.right.to_latex_string()
1408 )
1409 }
1410}
1411
1412impl NotNormalAtomicFact {
1413 pub fn to_latex_string(&self) -> String {
1414 let pred = self.predicate.to_latex_string();
1415 let args = self
1416 .body
1417 .iter()
1418 .map(|o| o.to_latex_string())
1419 .collect::<Vec<_>>()
1420 .join(", ");
1421 format!(r"\neg \left( \$ {}\left( {}\right) \right)", pred, args)
1422 }
1423}
1424
1425impl NotRestrictFact {
1426 pub fn to_latex_string(&self) -> String {
1427 format!(
1428 r"\neg \left( {} \mathrel{{\$}} \mathrm{{{}}}\, {} \right)",
1429 self.obj.to_latex_string(),
1430 RESTRICT_FN_IN,
1431 self.obj_cannot_restrict_to_fn_set.to_latex_string()
1432 )
1433 }
1434}
1435
1436impl NotSubsetFact {
1437 pub fn to_latex_string(&self) -> String {
1438 format!(
1439 r"\neg \left( {} \subseteq {} \right)",
1440 self.left.to_latex_string(),
1441 self.right.to_latex_string()
1442 )
1443 }
1444}
1445
1446impl NotSupersetFact {
1447 pub fn to_latex_string(&self) -> String {
1448 format!(
1449 r"\neg \left( {} \supseteq {} \right)",
1450 self.left.to_latex_string(),
1451 self.right.to_latex_string()
1452 )
1453 }
1454}
1455
1456impl Number {
1457 pub fn to_latex_string(&self) -> String {
1458 self.normalized_value.clone()
1459 }
1460}
1461
1462impl ObjAtIndex {
1463 pub fn to_latex_string(&self) -> String {
1464 format!(
1465 r"{}\left[ {} \right]",
1466 self.obj.to_latex_string(),
1467 self.index.to_latex_string()
1468 )
1469 }
1470}
1471
1472impl OrFact {
1473 pub fn to_latex_string(&self) -> String {
1474 self.facts
1475 .iter()
1476 .map(|f| f.to_latex_string())
1477 .collect::<Vec<_>>()
1478 .join(r" \lor ")
1479 }
1480}
1481
1482impl ParamDefWithType {
1483 pub fn to_latex_string(&self) -> String {
1484 self.groups
1485 .iter()
1486 .map(|g| g.to_latex_string())
1487 .collect::<Vec<_>>()
1488 .join(", ")
1489 }
1490}
1491
1492impl ParamGroupWithParamType {
1493 pub fn to_latex_string(&self) -> String {
1494 let names = self
1495 .params
1496 .iter()
1497 .map(|p| latex_local_ident(p))
1498 .collect::<Vec<_>>()
1499 .join(", ");
1500 format!(r"{}, {}", names, self.param_type.to_latex_string())
1501 }
1502}
1503
1504impl ParamType {
1505 pub fn to_latex_string(&self) -> String {
1506 match self {
1507 ParamType::Set(_) => format!(r"\mathrm{{{}}}", SET),
1508 ParamType::NonemptySet(_) => format!(r"\mathrm{{{}}}", NONEMPTY_SET),
1509 ParamType::FiniteSet(_) => format!(r"\mathrm{{{}}}", FINITE_SET),
1510 ParamType::Restrictive(fs) => format!(
1511 r"\mathrm{{{}}} {}{}{}",
1512 RESTRICTIVE,
1513 "(",
1514 Obj::FnSet(fs.clone()).to_latex_string(),
1515 ")"
1516 ),
1517 ParamType::Obj(o) => o.to_latex_string(),
1518 }
1519 }
1520}
1521
1522impl Pow {
1523 pub fn to_latex_string(&self) -> String {
1524 format!(
1525 "{{{}}}^{{{}}}",
1526 self.base.to_latex_string(),
1527 self.exponent.to_latex_string()
1528 )
1529 }
1530}
1531
1532impl PowerSet {
1533 pub fn to_latex_string(&self) -> String {
1534 format!(r"\mathcal{{P}}\left( {}\right)", self.set.to_latex_string())
1535 }
1536}
1537
1538impl Proj {
1539 pub fn to_latex_string(&self) -> String {
1540 format!(
1541 r"\operatorname{{{}}}\left( {}, {} \right)",
1542 PROJ,
1543 self.set.to_latex_string(),
1544 self.dim.to_latex_string()
1545 )
1546 }
1547}
1548
1549impl ProveStmt {
1550 pub fn to_latex_string(&self) -> String {
1551 if self.proof.is_empty() {
1552 return r"\text{\texttt{(empty proof)}}".to_string();
1553 }
1554 let rows: Vec<String> = self
1555 .proof
1556 .iter()
1557 .map(|st| format!(r"& \quad {}", st.to_latex_string()))
1558 .collect();
1559 format!(
1560 "\\begin{{aligned}}\n{}\n\\end{{aligned}}",
1561 rows.join(" \\\\\n")
1562 )
1563 }
1564}
1565
1566impl Range {
1567 pub fn to_latex_string(&self) -> String {
1568 format!(
1569 r"\operatorname{{{}}}\left( {}, {} \right)",
1570 RANGE,
1571 self.start.to_latex_string(),
1572 self.end.to_latex_string()
1573 )
1574 }
1575}
1576
1577impl RestrictFact {
1578 pub fn to_latex_string(&self) -> String {
1579 format!(
1580 r"{} \mathrel{{\$}} \mathrm{{{}}}\, {}",
1581 self.obj.to_latex_string(),
1582 RESTRICT_FN_IN,
1583 self.obj_can_restrict_to_fn_set.to_latex_string()
1584 )
1585 }
1586}
1587
1588impl RunFileStmt {
1589 pub fn to_latex_string(&self) -> String {
1590 format!(
1591 r"\operatorname{{{}}}\ \texttt{{{}}}",
1592 RUN_FILE,
1593 latex_texttt_escape(&self.file_path)
1594 )
1595 }
1596}
1597
1598impl SeqSet {
1599 pub fn to_latex_string(&self) -> String {
1600 format!(
1601 r"\operatorname{{{}}}\left( {}\right)",
1602 SEQ,
1603 self.set.to_latex_string()
1604 )
1605 }
1606}
1607
1608impl SetBuilder {
1609 pub fn to_latex_string(&self) -> String {
1610 let cond = self
1611 .facts
1612 .iter()
1613 .map(|f| f.to_latex_string())
1614 .collect::<Vec<_>>()
1615 .join(r" \land ");
1616 format!(
1617 r"\left\{{ {} \in {} \,\middle|\, {} \right\}}",
1618 latex_local_ident(&self.param),
1619 self.param_set.to_latex_string(),
1620 cond
1621 )
1622 }
1623}
1624
1625impl SetDiff {
1626 pub fn to_latex_string(&self) -> String {
1627 format!(
1628 r"\operatorname{{{}}}\left( {}, {} \right)",
1629 SET_DIFF,
1630 self.left.to_latex_string(),
1631 self.right.to_latex_string()
1632 )
1633 }
1634}
1635
1636impl SetMinus {
1637 pub fn to_latex_string(&self) -> String {
1638 format!(
1639 r"{} \setminus {}",
1640 self.left.to_latex_string(),
1641 self.right.to_latex_string()
1642 )
1643 }
1644}
1645
1646impl Sub {
1647 pub fn to_latex_string(&self) -> String {
1648 format!(
1649 "{} - {}",
1650 self.left.to_latex_string(),
1651 self.right.to_latex_string()
1652 )
1653 }
1654}
1655
1656impl SubsetFact {
1657 pub fn to_latex_string(&self) -> String {
1658 format!(
1659 r"{} \subseteq {}",
1660 self.left.to_latex_string(),
1661 self.right.to_latex_string()
1662 )
1663 }
1664}
1665
1666impl SupersetFact {
1667 pub fn to_latex_string(&self) -> String {
1668 format!(
1669 r"{} \supseteq {}",
1670 self.left.to_latex_string(),
1671 self.right.to_latex_string()
1672 )
1673 }
1674}
1675
1676impl Tuple {
1677 pub fn to_latex_string(&self) -> String {
1678 let inner = self
1679 .args
1680 .iter()
1681 .map(|o| o.to_latex_string())
1682 .collect::<Vec<_>>()
1683 .join(", ");
1684 format!(r"\left( {} \right)", inner)
1685 }
1686}
1687
1688impl TupleDim {
1689 pub fn to_latex_string(&self) -> String {
1690 format!(
1691 r"\operatorname{{{}}}\left( {}\right)",
1692 TUPLE_DIM,
1693 self.arg.to_latex_string()
1694 )
1695 }
1696}
1697
1698impl Union {
1699 pub fn to_latex_string(&self) -> String {
1700 format!(
1701 r"{} \cup {}",
1702 self.left.to_latex_string(),
1703 self.right.to_latex_string()
1704 )
1705 }
1706}
1707
1708impl WitnessExistFact {
1709 pub fn to_latex_string(&self) -> String {
1710 let names = self
1711 .equal_tos
1712 .iter()
1713 .map(|o| o.to_latex_string())
1714 .collect::<Vec<_>>()
1715 .join(", ");
1716 let facts = self
1717 .exist_fact_in_witness
1718 .facts()
1719 .iter()
1720 .map(|f| f.to_latex_string())
1721 .collect::<Vec<_>>()
1722 .join(", ");
1723 let head = format!(
1724 r"\mathrm{{witness}}\ {} : {} \mathrm{{st}} \left\{{ {}\right\}}",
1725 names,
1726 self.exist_fact_in_witness
1727 .params_def_with_type()
1728 .to_latex_string(),
1729 facts
1730 );
1731 if self.proof.is_empty() {
1732 head
1733 } else {
1734 let mut rows = vec![format!(r"{} &", head)];
1735 for st in &self.proof {
1736 rows.push(format!(r"& \quad {}", st.to_latex_string()));
1737 }
1738 format!(
1739 "\\begin{{aligned}}\n{}\n\\end{{aligned}}",
1740 rows.join(" \\\\\n")
1741 )
1742 }
1743 }
1744}
1745
1746impl WitnessNonemptySet {
1747 pub fn to_latex_string(&self) -> String {
1748 let head = format!(
1749 r"\mathrm{{witness}}\ {} {}",
1750 self.obj.to_latex_string(),
1751 self.set.to_latex_string()
1752 );
1753 if self.proof.is_empty() {
1754 head
1755 } else {
1756 let mut rows = vec![format!(r"{} &", head)];
1757 for st in &self.proof {
1758 rows.push(format!(r"& \quad {}", st.to_latex_string()));
1759 }
1760 format!(
1761 "\\begin{{aligned}}\n{}\n\\end{{aligned}}",
1762 rows.join(" \\\\\n")
1763 )
1764 }
1765 }
1766}
1767
1768impl ImportGlobalModuleStmt {
1769 pub fn to_latex_string(&self) -> String {
1770 match &self.as_mod_name {
1771 Some(m) => format!(
1772 r"\operatorname{{{}}}\ {}\ \mathrm{{as}}\ {}",
1773 IMPORT,
1774 latex_local_ident(&self.mod_name),
1775 latex_local_ident(m)
1776 ),
1777 None => format!(
1778 r"\operatorname{{{}}}\ {}",
1779 IMPORT,
1780 latex_local_ident(&self.mod_name)
1781 ),
1782 }
1783 }
1784}
1785
1786impl ImportRelativePathStmt {
1787 pub fn to_latex_string(&self) -> String {
1788 let path = latex_texttt_escape(&self.path);
1789 match &self.as_mod_name {
1790 Some(m) => format!(
1791 r"\operatorname{{{}}}\ \texttt{{{}}}\ \mathrm{{as}}\ {}",
1792 IMPORT,
1793 path,
1794 latex_local_ident(m)
1795 ),
1796 None => format!(r"\operatorname{{{}}}\ \texttt{{{}}}", IMPORT, path),
1797 }
1798 }
1799}
1800
1801impl ImportStmt {
1802 pub fn to_latex_string(&self) -> String {
1803 match self {
1804 ImportStmt::ImportRelativePath(s) => s.to_latex_string(),
1805 ImportStmt::ImportGlobalModule(s) => s.to_latex_string(),
1806 }
1807 }
1808}
1809
1810impl StandardSet {
1811 pub fn to_latex_string(&self) -> String {
1812 match self {
1813 StandardSet::N => r"\mathbb{N}".to_string(),
1814 StandardSet::NPos => r"\mathbb{N}_{>0}".to_string(),
1815 StandardSet::Z => r"\mathbb{Z}".to_string(),
1816 StandardSet::ZNeg => r"\mathbb{Z}_{<0}".to_string(),
1817 StandardSet::ZNz => r"\mathbb{Z}\setminus\{0\}".to_string(),
1818 StandardSet::Q => r"\mathbb{Q}".to_string(),
1819 StandardSet::QPos => r"\mathbb{Q}_{>0}".to_string(),
1820 StandardSet::QNeg => r"\mathbb{Q}_{<0}".to_string(),
1821 StandardSet::QNz => r"\mathbb{Q}\setminus\{0\}".to_string(),
1822 StandardSet::R => r"\mathbb{R}".to_string(),
1823 StandardSet::RPos => r"\mathbb{R}_{>0}".to_string(),
1824 StandardSet::RNeg => r"\mathbb{R}_{<0}".to_string(),
1825 StandardSet::RNz => r"\mathbb{R}\setminus\{0\}".to_string(),
1826 }
1827 }
1828}
1829
1830impl Fact {
1831 pub fn to_latex_string(&self) -> String {
1832 match self {
1833 Fact::AtomicFact(x) => x.to_latex_string(),
1834 Fact::ExistFact(x) => x.to_latex_string(),
1835 Fact::OrFact(x) => x.to_latex_string(),
1836 Fact::AndFact(x) => x.to_latex_string(),
1837 Fact::ChainFact(x) => x.to_latex_string(),
1838 Fact::ForallFact(x) => x.to_latex_string(),
1839 Fact::ForallFactWithIff(x) => x.to_latex_string(),
1840 Fact::NotForall(x) => x.to_latex_string(),
1841 }
1842 }
1843}
1844
1845impl AtomicFact {
1846 pub fn to_latex_string(&self) -> String {
1847 match self {
1848 AtomicFact::NormalAtomicFact(x) => x.to_latex_string(),
1849 AtomicFact::EqualFact(x) => x.to_latex_string(),
1850 AtomicFact::LessFact(x) => x.to_latex_string(),
1851 AtomicFact::GreaterFact(x) => x.to_latex_string(),
1852 AtomicFact::LessEqualFact(x) => x.to_latex_string(),
1853 AtomicFact::GreaterEqualFact(x) => x.to_latex_string(),
1854 AtomicFact::IsSetFact(x) => x.to_latex_string(),
1855 AtomicFact::IsNonemptySetFact(x) => x.to_latex_string(),
1856 AtomicFact::IsFiniteSetFact(x) => x.to_latex_string(),
1857 AtomicFact::InFact(x) => x.to_latex_string(),
1858 AtomicFact::IsCartFact(x) => x.to_latex_string(),
1859 AtomicFact::IsTupleFact(x) => x.to_latex_string(),
1860 AtomicFact::SubsetFact(x) => x.to_latex_string(),
1861 AtomicFact::SupersetFact(x) => x.to_latex_string(),
1862 AtomicFact::RestrictFact(x) => x.to_latex_string(),
1863 AtomicFact::NotRestrictFact(x) => x.to_latex_string(),
1864 AtomicFact::NotNormalAtomicFact(x) => x.to_latex_string(),
1865 AtomicFact::NotEqualFact(x) => x.to_latex_string(),
1866 AtomicFact::NotLessFact(x) => x.to_latex_string(),
1867 AtomicFact::NotGreaterFact(x) => x.to_latex_string(),
1868 AtomicFact::NotLessEqualFact(x) => x.to_latex_string(),
1869 AtomicFact::NotGreaterEqualFact(x) => x.to_latex_string(),
1870 AtomicFact::NotIsSetFact(x) => x.to_latex_string(),
1871 AtomicFact::NotIsNonemptySetFact(x) => x.to_latex_string(),
1872 AtomicFact::NotIsFiniteSetFact(x) => x.to_latex_string(),
1873 AtomicFact::NotInFact(x) => x.to_latex_string(),
1874 AtomicFact::NotIsCartFact(x) => x.to_latex_string(),
1875 AtomicFact::NotIsTupleFact(x) => x.to_latex_string(),
1876 AtomicFact::NotSubsetFact(x) => x.to_latex_string(),
1877 AtomicFact::NotSupersetFact(x) => x.to_latex_string(),
1878 AtomicFact::FnEqualInFact(f) => format!(
1879 r"\mathsf{{fn\_eq\_in}}({},{},{})",
1880 f.left.to_latex_string(),
1881 f.right.to_latex_string(),
1882 f.set.to_latex_string(),
1883 ),
1884 AtomicFact::FnEqualFact(f) => format!(
1885 r"\mathsf{{fn\_eq}}({},{})",
1886 f.left.to_latex_string(),
1887 f.right.to_latex_string(),
1888 ),
1889 }
1890 }
1891}
1892
1893impl Obj {
1894 pub fn to_latex_string(&self) -> String {
1895 match self {
1896 Obj::Atom(AtomObj::Identifier(x)) => x.to_latex_string(),
1897 Obj::Atom(AtomObj::IdentifierWithMod(x)) => x.to_latex_string(),
1898 Obj::FnObj(x) => x.to_latex_string(),
1899 Obj::Number(x) => x.to_latex_string(),
1900 Obj::Add(x) => x.to_latex_string(),
1901 Obj::Sub(x) => x.to_latex_string(),
1902 Obj::Mul(x) => x.to_latex_string(),
1903 Obj::Div(x) => x.to_latex_string(),
1904 Obj::Mod(x) => x.to_latex_string(),
1905 Obj::Pow(x) => x.to_latex_string(),
1906 Obj::Abs(x) => x.to_latex_string(),
1907 Obj::Log(x) => x.to_latex_string(),
1908 Obj::Max(x) => x.to_latex_string(),
1909 Obj::Min(x) => x.to_latex_string(),
1910 Obj::Union(x) => x.to_latex_string(),
1911 Obj::Intersect(x) => x.to_latex_string(),
1912 Obj::SetMinus(x) => x.to_latex_string(),
1913 Obj::SetDiff(x) => x.to_latex_string(),
1914 Obj::Cup(x) => x.to_latex_string(),
1915 Obj::Cap(x) => x.to_latex_string(),
1916 Obj::PowerSet(x) => x.to_latex_string(),
1917 Obj::ListSet(x) => x.to_latex_string(),
1918 Obj::SetBuilder(x) => x.to_latex_string(),
1919 Obj::FnSet(x) => x.to_latex_string(),
1920 Obj::AnonymousFn(x) => x.to_latex_string(),
1921 Obj::Cart(x) => x.to_latex_string(),
1922 Obj::CartDim(x) => x.to_latex_string(),
1923 Obj::Proj(x) => x.to_latex_string(),
1924 Obj::TupleDim(x) => x.to_latex_string(),
1925 Obj::Tuple(x) => x.to_latex_string(),
1926 Obj::Count(x) => x.to_latex_string(),
1927 Obj::Sum(x) => x.to_latex_string(),
1928 Obj::Product(x) => x.to_latex_string(),
1929 Obj::Range(x) => x.to_latex_string(),
1930 Obj::ClosedRange(x) => x.to_latex_string(),
1931 Obj::FiniteSeqSet(x) => x.to_latex_string(),
1932 Obj::SeqSet(x) => x.to_latex_string(),
1933 Obj::FiniteSeqListObj(x) => x.to_latex_string(),
1934 Obj::Choose(x) => x.to_latex_string(),
1935 Obj::ObjAtIndex(x) => x.to_latex_string(),
1936 Obj::StandardSet(x) => x.to_latex_string(),
1937 Obj::FamilyObj(x) => x.to_latex_string(),
1938 Obj::Atom(AtomObj::Forall(x)) => latex_local_ident(&x.name),
1939 Obj::Atom(AtomObj::Def(x)) => latex_local_ident(&x.name),
1940 Obj::Atom(AtomObj::Exist(x)) => latex_local_ident(&x.name),
1941 Obj::Atom(AtomObj::SetBuilder(x)) => latex_local_ident(&x.name),
1942 Obj::Atom(AtomObj::FnSet(x)) => latex_local_ident(&x.name),
1943 Obj::Atom(AtomObj::Induc(x)) => latex_local_ident(&x.name),
1944 Obj::Atom(AtomObj::DefAlgo(x)) => latex_local_ident(&x.name),
1945 Obj::MatrixSet(x) => x.to_latex_string(),
1946 Obj::MatrixListObj(x) => x.to_latex_string(),
1947 Obj::MatrixAdd(x) => x.to_latex_string(),
1948 Obj::MatrixSub(x) => x.to_latex_string(),
1949 Obj::MatrixMul(x) => x.to_latex_string(),
1950 Obj::MatrixScalarMul(x) => x.to_latex_string(),
1951 Obj::MatrixPow(x) => x.to_latex_string(),
1952 }
1953 }
1954}
1955
1956impl Stmt {
1957 pub fn to_latex_string(&self) -> String {
1958 match self {
1959 Stmt::Fact(x) => x.to_latex_string(),
1960 Stmt::DefLetStmt(x) => x.to_latex_string(),
1961 Stmt::DefPropStmt(x) => x.to_latex_string(),
1962 Stmt::DefAbstractPropStmt(x) => x.to_latex_string(),
1963 Stmt::HaveObjInNonemptySetStmt(x) => x.to_latex_string(),
1964 Stmt::HaveObjEqualStmt(x) => x.to_latex_string(),
1965 Stmt::HaveByExistStmt(x) => x.to_latex_string(),
1966 Stmt::HaveFnEqualStmt(x) => x.to_latex_string(),
1967 Stmt::HaveFnEqualCaseByCaseStmt(x) => x.to_latex_string(),
1968 Stmt::HaveFnByInducStmt(x) => x.to_latex_string(),
1969 Stmt::DefFamilyStmt(x) => x.to_latex_string(),
1970 Stmt::DefAlgoStmt(x) => x.to_latex_string(),
1971 Stmt::ClaimStmt(x) => x.to_latex_string(),
1972 Stmt::KnowStmt(x) => x.to_latex_string(),
1973 Stmt::ProveStmt(x) => x.to_latex_string(),
1974 Stmt::ImportStmt(x) => x.to_latex_string(),
1975 Stmt::DoNothingStmt(x) => x.to_latex_string(),
1976 Stmt::ClearStmt(x) => x.to_latex_string(),
1977 Stmt::RunFileStmt(x) => x.to_latex_string(),
1978 Stmt::EvalStmt(x) => x.to_latex_string(),
1979 Stmt::WitnessExistFact(x) => x.to_latex_string(),
1980 Stmt::WitnessNonemptySet(x) => x.to_latex_string(),
1981 Stmt::ByCasesStmt(x) => x.to_latex_string(),
1982 Stmt::ByContraStmt(x) => x.to_latex_string(),
1983 Stmt::ByEnumerateFiniteSetStmt(x) => x.to_latex_string(),
1984 Stmt::ByInducStmt(x) => x.to_latex_string(),
1985 Stmt::ByForStmt(x) => x.to_latex_string(),
1986 Stmt::ByExtensionStmt(x) => x.to_latex_string(),
1987 Stmt::ByFnStmt(x) => x.to_latex_string(),
1988 Stmt::ByFamilyStmt(x) => x.to_latex_string(),
1989 Stmt::ByTuple(x) => x.to_latex_string(),
1990 Stmt::ByFnSetStmt(x) => x.to_latex_string(),
1991 Stmt::ByEnumerateClosedRangeStmt(x) => x.to_latex_string(),
1992 }
1993 }
1994}