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