1use crate::infer::obj_eligible_for_known_objs_in_fn_sets;
2use crate::prelude::*;
3use crate::verify::{
4 number_is_in_n, number_is_in_n_pos, number_is_in_q_neg, number_is_in_q_nz, number_is_in_q_pos,
5 number_is_in_r_neg, number_is_in_r_nz, number_is_in_r_pos, number_is_in_z, number_is_in_z_neg,
6 number_is_in_z_nz, verify_equality_by_builtin_rules::verify_equality_by_they_are_the_same,
7 verify_number_in_standard_set::is_integer_after_simplification, VerifyState,
8};
9fn number_in_set_verified_by_builtin_rules_result(in_fact: &InFact, reason: &str) -> StmtResult {
10 StmtResult::FactualStmtSuccess(
11 FactualStmtSuccess::new_with_verified_by_builtin_rules_recording_stmt(
12 in_fact.clone().into(),
13 reason.to_string(),
14 Vec::new(),
15 ),
16 )
17}
18
19fn not_in_fact_verified_by_builtin_rules_result(
20 not_in_fact: &NotInFact,
21 reason: &str,
22) -> StmtResult {
23 StmtResult::FactualStmtSuccess(
24 FactualStmtSuccess::new_with_verified_by_builtin_rules_recording_stmt(
25 not_in_fact.clone().into(),
26 reason.to_string(),
27 Vec::new(),
28 ),
29 )
30}
31
32fn arithmetic_obj_in_r_verified_by_builtin_rules_result(in_fact: &InFact) -> StmtResult {
33 StmtResult::FactualStmtSuccess(
34 FactualStmtSuccess::new_with_verified_by_builtin_rules_recording_stmt(
35 in_fact.clone().into(),
36 "arithmetic expression is in R".to_string(),
37 Vec::new(),
38 ),
39 )
40}
41
42fn builtin_in_fact_result_for_evaluated_number_in_standard_set(
43 in_fact: &InFact,
44 evaluated_number: &Number,
45 standard_set: &StandardSet,
46) -> StmtResult {
47 match standard_set {
48 StandardSet::R => number_in_set_verified_by_builtin_rules_result(in_fact, "number in R"),
49 StandardSet::RPos => {
50 if number_is_in_r_pos(evaluated_number) {
51 number_in_set_verified_by_builtin_rules_result(in_fact, "number in R_pos")
52 } else {
53 StmtResult::StmtUnknown(StmtUnknown::new())
54 }
55 }
56 StandardSet::RNeg => {
57 if number_is_in_r_neg(evaluated_number) {
58 number_in_set_verified_by_builtin_rules_result(in_fact, "number in R_neg")
59 } else {
60 StmtResult::StmtUnknown(StmtUnknown::new())
61 }
62 }
63 StandardSet::RNz => {
64 if number_is_in_r_nz(evaluated_number) {
65 number_in_set_verified_by_builtin_rules_result(in_fact, "number in R_nz")
66 } else {
67 StmtResult::StmtUnknown(StmtUnknown::new())
68 }
69 }
70 StandardSet::Q => number_in_set_verified_by_builtin_rules_result(in_fact, "number in Q"),
71 StandardSet::QPos => {
72 if number_is_in_q_pos(evaluated_number) {
73 number_in_set_verified_by_builtin_rules_result(in_fact, "number in Q_pos")
74 } else {
75 StmtResult::StmtUnknown(StmtUnknown::new())
76 }
77 }
78 StandardSet::QNeg => {
79 if number_is_in_q_neg(evaluated_number) {
80 number_in_set_verified_by_builtin_rules_result(in_fact, "number in Q_neg")
81 } else {
82 StmtResult::StmtUnknown(StmtUnknown::new())
83 }
84 }
85 StandardSet::QNz => {
86 if number_is_in_q_nz(evaluated_number) {
87 number_in_set_verified_by_builtin_rules_result(in_fact, "number in Q_nz")
88 } else {
89 StmtResult::StmtUnknown(StmtUnknown::new())
90 }
91 }
92 StandardSet::Z => {
93 if number_is_in_z(evaluated_number) {
94 number_in_set_verified_by_builtin_rules_result(in_fact, "number in Z")
95 } else {
96 StmtResult::StmtUnknown(StmtUnknown::new())
97 }
98 }
99 StandardSet::ZNeg => {
100 if number_is_in_z_neg(evaluated_number) {
101 number_in_set_verified_by_builtin_rules_result(in_fact, "number in Z_neg")
102 } else {
103 StmtResult::StmtUnknown(StmtUnknown::new())
104 }
105 }
106 StandardSet::ZNz => {
107 if number_is_in_z_nz(evaluated_number) {
108 number_in_set_verified_by_builtin_rules_result(in_fact, "number in Z_nz")
109 } else {
110 StmtResult::StmtUnknown(StmtUnknown::new())
111 }
112 }
113 StandardSet::N => {
114 if number_is_in_n(evaluated_number) {
115 number_in_set_verified_by_builtin_rules_result(in_fact, "number in N")
116 } else {
117 StmtResult::StmtUnknown(StmtUnknown::new())
118 }
119 }
120 StandardSet::NPos => {
121 if number_is_in_n_pos(evaluated_number) {
122 number_in_set_verified_by_builtin_rules_result(in_fact, "number in N_pos")
123 } else {
124 StmtResult::StmtUnknown(StmtUnknown::new())
125 }
126 }
127 }
128}
129
130fn builtin_not_in_fact_result_for_evaluated_number_in_standard_set(
131 not_in_fact: &NotInFact,
132 evaluated_number: &Number,
133 standard_set: &StandardSet,
134) -> StmtResult {
135 match standard_set {
136 StandardSet::R | StandardSet::Q => StmtResult::StmtUnknown(StmtUnknown::new()),
137 StandardSet::RPos => {
138 if !number_is_in_r_pos(evaluated_number) {
139 not_in_fact_verified_by_builtin_rules_result(not_in_fact, "number not in R_pos")
140 } else {
141 StmtResult::StmtUnknown(StmtUnknown::new())
142 }
143 }
144 StandardSet::RNeg => {
145 if !number_is_in_r_neg(evaluated_number) {
146 not_in_fact_verified_by_builtin_rules_result(not_in_fact, "number not in R_neg")
147 } else {
148 StmtResult::StmtUnknown(StmtUnknown::new())
149 }
150 }
151 StandardSet::RNz => {
152 if !number_is_in_r_nz(evaluated_number) {
153 not_in_fact_verified_by_builtin_rules_result(not_in_fact, "number not in R_nz")
154 } else {
155 StmtResult::StmtUnknown(StmtUnknown::new())
156 }
157 }
158 StandardSet::QPos => {
159 if !number_is_in_q_pos(evaluated_number) {
160 not_in_fact_verified_by_builtin_rules_result(not_in_fact, "number not in Q_pos")
161 } else {
162 StmtResult::StmtUnknown(StmtUnknown::new())
163 }
164 }
165 StandardSet::QNeg => {
166 if !number_is_in_q_neg(evaluated_number) {
167 not_in_fact_verified_by_builtin_rules_result(not_in_fact, "number not in Q_neg")
168 } else {
169 StmtResult::StmtUnknown(StmtUnknown::new())
170 }
171 }
172 StandardSet::QNz => {
173 if !number_is_in_q_nz(evaluated_number) {
174 not_in_fact_verified_by_builtin_rules_result(not_in_fact, "number not in Q_nz")
175 } else {
176 StmtResult::StmtUnknown(StmtUnknown::new())
177 }
178 }
179 StandardSet::Z => {
180 if !number_is_in_z(evaluated_number) {
181 not_in_fact_verified_by_builtin_rules_result(not_in_fact, "number not in Z")
182 } else {
183 StmtResult::StmtUnknown(StmtUnknown::new())
184 }
185 }
186 StandardSet::ZNeg => {
187 if !number_is_in_z_neg(evaluated_number) {
188 not_in_fact_verified_by_builtin_rules_result(not_in_fact, "number not in Z_neg")
189 } else {
190 StmtResult::StmtUnknown(StmtUnknown::new())
191 }
192 }
193 StandardSet::ZNz => {
194 if !number_is_in_z_nz(evaluated_number) {
195 not_in_fact_verified_by_builtin_rules_result(not_in_fact, "number not in Z_nz")
196 } else {
197 StmtResult::StmtUnknown(StmtUnknown::new())
198 }
199 }
200 StandardSet::N => {
201 if !number_is_in_n(evaluated_number) {
202 not_in_fact_verified_by_builtin_rules_result(not_in_fact, "number not in N")
203 } else {
204 StmtResult::StmtUnknown(StmtUnknown::new())
205 }
206 }
207 StandardSet::NPos => {
208 if !number_is_in_n_pos(evaluated_number) {
209 not_in_fact_verified_by_builtin_rules_result(not_in_fact, "number not in N_pos")
210 } else {
211 StmtResult::StmtUnknown(StmtUnknown::new())
212 }
213 }
214 }
215}
216
217impl Runtime {
218 pub fn verify_not_in_fact_with_builtin_rules(
219 &mut self,
220 not_in_fact: &NotInFact,
221 _verify_state: &VerifyState,
222 ) -> Result<StmtResult, RuntimeError> {
223 if let Obj::StandardSet(standard_set) = ¬_in_fact.set {
224 if !matches!(¬_in_fact.element, Obj::Number(_)) {
225 if let Some(evaluated_number) =
226 not_in_fact.element.evaluate_to_normalized_decimal_number()
227 {
228 return Ok(
229 builtin_not_in_fact_result_for_evaluated_number_in_standard_set(
230 not_in_fact,
231 &evaluated_number,
232 standard_set,
233 ),
234 );
235 }
236 }
237 }
238 match (¬_in_fact.element, ¬_in_fact.set) {
239 (Obj::Number(num), Obj::StandardSet(standard_set)) => Ok(
240 builtin_not_in_fact_result_for_evaluated_number_in_standard_set(
241 not_in_fact,
242 num,
243 standard_set,
244 ),
245 ),
246 _ => Ok((StmtUnknown::new()).into()),
247 }
248 }
249
250 fn maybe_verify_in_fact_max_min_pair_closed_standard_set(
251 &mut self,
252 in_fact: &InFact,
253 verify_state: &VerifyState,
254 ) -> Result<Option<StmtResult>, RuntimeError> {
255 let (left, right, set) = match (&in_fact.element, &in_fact.set) {
256 (Obj::Max(m), Obj::StandardSet(s)) => (m.left.as_ref(), m.right.as_ref(), s.clone()),
257 (Obj::Min(m), Obj::StandardSet(s)) => (m.left.as_ref(), m.right.as_ref(), s.clone()),
258 _ => return Ok(None),
259 };
260 if !matches!(
261 set,
262 StandardSet::RPos
263 | StandardSet::QPos
264 | StandardSet::RNeg
265 | StandardSet::QNeg
266 | StandardSet::ZNeg
267 | StandardSet::N
268 | StandardSet::NPos
269 ) {
270 return Ok(None);
271 }
272 let reason = format!("max/min: both operands in {}", set);
273 let set_obj: Obj = set.into();
274 let lf = in_fact.line_file.clone();
275 for operand in [left, right] {
276 let f: AtomicFact = InFact::new(operand.clone(), set_obj.clone(), lf.clone()).into();
277 if !self.non_equational_atomic_fact_holds_by_full_verify_pipeline(&f, verify_state)? {
278 return Ok(Some((StmtUnknown::new()).into()));
279 }
280 }
281 Ok(Some(number_in_set_verified_by_builtin_rules_result(
282 in_fact,
283 reason.as_str(),
284 )))
285 }
286
287 fn verify_in_fact_sum_or_product_in_r(
290 &mut self,
291 in_fact: &InFact,
292 verify_state: &VerifyState,
293 reason: &str,
294 ) -> Result<StmtResult, RuntimeError> {
295 if self
296 .verify_obj_well_defined_and_store_cache(&in_fact.element, verify_state)
297 .is_ok()
298 {
299 Ok(number_in_set_verified_by_builtin_rules_result(
300 in_fact, reason,
301 ))
302 } else {
303 Ok((StmtUnknown::new()).into())
304 }
305 }
306
307 fn iterated_op_func_ret_set(&self, func: &Obj) -> Option<Obj> {
308 match func {
309 Obj::AnonymousFn(anon) => Some((*anon.body.ret_set).clone()),
310 Obj::FnObj(fn_obj) if fn_obj.body.is_empty() => match fn_obj.head.as_ref() {
311 FnObjHead::AnonymousFnLiteral(anon) => Some((*anon.body.ret_set).clone()),
312 _ => {
313 let function_name_obj: Obj = (*fn_obj.head).clone().into();
314 self.get_object_in_fn_set_or_restrict(&function_name_obj)
315 .map(|fn_set_body| (*fn_set_body.ret_set).clone())
316 }
317 },
318 _ => self
319 .get_object_in_fn_set_or_restrict(func)
320 .map(|fn_set_body| (*fn_set_body.ret_set).clone()),
321 }
322 }
323
324 fn verify_in_fact_sum_or_product_in_z_by_iterand_ret_set(
329 &mut self,
330 in_fact: &InFact,
331 func: &Obj,
332 verify_state: &VerifyState,
333 op: &str,
334 ) -> Result<StmtResult, RuntimeError> {
335 if self
336 .verify_obj_well_defined_and_store_cache(&in_fact.element, verify_state)
337 .is_err()
338 {
339 return Ok((StmtUnknown::new()).into());
340 }
341 let Some(ret_set) = self.iterated_op_func_ret_set(func) else {
342 return Ok((StmtUnknown::new()).into());
343 };
344 let z_obj: Obj = StandardSet::Z.into();
345 let n_pos_obj: Obj = StandardSet::NPos.into();
346 let reason = if verify_equality_by_they_are_the_same(&ret_set, &z_obj) {
347 format!("{op}: iterand return set is Z")
348 } else if verify_equality_by_they_are_the_same(&ret_set, &n_pos_obj) {
349 format!("{op}: iterand return set is N_pos (subset of Z)")
350 } else {
351 return Ok((StmtUnknown::new()).into());
352 };
353 Ok(number_in_set_verified_by_builtin_rules_result(
354 in_fact,
355 reason.as_str(),
356 ))
357 }
358
359 fn verify_in_fact_sum_or_product_in_q_by_iterand_ret_set(
362 &mut self,
363 in_fact: &InFact,
364 func: &Obj,
365 verify_state: &VerifyState,
366 op: &str,
367 ) -> Result<StmtResult, RuntimeError> {
368 if self
369 .verify_obj_well_defined_and_store_cache(&in_fact.element, verify_state)
370 .is_err()
371 {
372 return Ok((StmtUnknown::new()).into());
373 }
374 let Some(ret_set) = self.iterated_op_func_ret_set(func) else {
375 return Ok((StmtUnknown::new()).into());
376 };
377 let q_obj: Obj = StandardSet::Q.into();
378 if !verify_equality_by_they_are_the_same(&ret_set, &q_obj) {
379 return Ok((StmtUnknown::new()).into());
380 }
381 let reason = format!("{op}: iterand return set is Q");
382 Ok(number_in_set_verified_by_builtin_rules_result(
383 in_fact,
384 reason.as_str(),
385 ))
386 }
387
388 fn verify_in_fact_sum_or_product_in_n_pos_by_iterand_ret_set(
392 &mut self,
393 in_fact: &InFact,
394 func: &Obj,
395 verify_state: &VerifyState,
396 op: &str,
397 ) -> Result<StmtResult, RuntimeError> {
398 if self
399 .verify_obj_well_defined_and_store_cache(&in_fact.element, verify_state)
400 .is_err()
401 {
402 return Ok((StmtUnknown::new()).into());
403 }
404 let Some(ret_set) = self.iterated_op_func_ret_set(func) else {
405 return Ok((StmtUnknown::new()).into());
406 };
407 let n_pos_obj: Obj = StandardSet::NPos.into();
408 if !verify_equality_by_they_are_the_same(&ret_set, &n_pos_obj) {
409 return Ok((StmtUnknown::new()).into());
410 }
411 let reason = format!("{op}: iterand return set is N_pos");
412 Ok(number_in_set_verified_by_builtin_rules_result(
413 in_fact,
414 reason.as_str(),
415 ))
416 }
417
418 fn verify_in_fact_fn_application_in_typed_return_set(
421 &mut self,
422 fn_obj: &FnObj,
423 in_fact: &InFact,
424 verify_state: &VerifyState,
425 ) -> Result<StmtResult, RuntimeError> {
426 let typed_ret = match fn_obj.head.as_ref() {
427 FnObjHead::AnonymousFnLiteral(a) => (*a.body.ret_set).clone(),
428 _ => {
429 let head_obj: Obj = (*fn_obj.head.clone()).into();
430 let Some(fn_set) = self.get_cloned_object_in_fn_set(&head_obj) else {
431 return Ok((StmtUnknown::new()).into());
432 };
433 (*fn_set.ret_set).clone()
434 }
435 };
436 let target = &in_fact.set;
437 let ret_matches = verify_equality_by_they_are_the_same(target, &typed_ret)
438 || self
439 .verify_equal_fact(
440 &EqualFact::new(target.clone(), typed_ret.clone(), in_fact.line_file.clone()),
441 verify_state,
442 )?
443 .is_true();
444 if !ret_matches {
445 return Ok((StmtUnknown::new()).into());
446 }
447 if self
448 .verify_obj_well_defined_and_store_cache(&Obj::FnObj(fn_obj.clone()), verify_state)
449 .is_err()
450 {
451 return Ok((StmtUnknown::new()).into());
452 }
453 Ok(
454 FactualStmtSuccess::new_with_verified_by_builtin_rules_recording_stmt(
455 in_fact.clone().into(),
456 "fn application in declared return set (well-defined under typing)".to_string(),
457 Vec::new(),
458 )
459 .into(),
460 )
461 }
462
463 pub fn verify_in_fact_with_builtin_rules(
464 &mut self,
465 in_fact: &InFact,
466 verify_state: &VerifyState,
467 ) -> Result<StmtResult, RuntimeError> {
468 if let Obj::StandardSet(standard_set) = &in_fact.set {
469 if !matches!(&in_fact.element, Obj::Number(_)) {
470 if let Some(evaluated_number) =
471 in_fact.element.evaluate_to_normalized_decimal_number()
472 {
473 let evaluation_membership_result =
474 builtin_in_fact_result_for_evaluated_number_in_standard_set(
475 in_fact,
476 &evaluated_number,
477 standard_set,
478 );
479 return Ok(evaluation_membership_result);
480 }
481 }
482 }
483 if let Some(result) =
484 self.maybe_verify_in_fact_max_min_pair_closed_standard_set(in_fact, verify_state)?
485 {
486 return Ok(result);
487 }
488 match (&in_fact.element, &in_fact.set) {
489 (Obj::Tuple(tuple), Obj::Cart(cart)) => {
490 return self.verify_in_fact_by_left_is_tuple_right_is_cart(
491 in_fact,
492 tuple,
493 cart,
494 verify_state,
495 );
496 }
497 (Obj::Number(num), Obj::StandardSet(standard_set)) => {
498 Ok(builtin_in_fact_result_for_evaluated_number_in_standard_set(
499 in_fact,
500 num,
501 standard_set,
502 ))
503 }
504 (Obj::Sum(sum), Obj::StandardSet(StandardSet::NPos)) => self
505 .verify_in_fact_sum_or_product_in_n_pos_by_iterand_ret_set(
506 in_fact,
507 sum.func.as_ref(),
508 verify_state,
509 "sum",
510 ),
511 (Obj::Product(product), Obj::StandardSet(StandardSet::NPos)) => self
512 .verify_in_fact_sum_or_product_in_n_pos_by_iterand_ret_set(
513 in_fact,
514 product.func.as_ref(),
515 verify_state,
516 "product",
517 ),
518 (Obj::Add(add), Obj::StandardSet(StandardSet::N)) => {
519 self.verify_in_fact_add_in_n_from_summands_in_n(in_fact, add, verify_state)
520 }
521 (Obj::Mul(mul), Obj::StandardSet(StandardSet::N)) => {
522 self.verify_in_fact_mul_in_n_from_factors_in_n(in_fact, mul, verify_state)
523 }
524 (Obj::Add(add), Obj::StandardSet(StandardSet::NPos)) => {
525 self.verify_in_fact_add_in_n_pos_from_n_pos_and_n(in_fact, add, verify_state)
526 }
527 (Obj::Mul(mul), Obj::StandardSet(StandardSet::NPos)) => {
528 self.verify_in_fact_mul_in_n_pos_from_factors_in_n_pos(in_fact, mul, verify_state)
529 }
530 (_, Obj::StandardSet(StandardSet::NPos)) => {
531 self.verify_in_fact_n_pos_by_zero_less_and_in_z_or_n(in_fact, verify_state)
532 }
533 (_, Obj::ClosedRange(closed_range)) => self
534 .verify_in_fact_closed_range_by_order_bounds(in_fact, closed_range, verify_state),
535 (_, Obj::Range(range)) => {
536 self.verify_in_fact_open_range_by_order_bounds(in_fact, range, verify_state)
537 }
538 (
539 Obj::Add(_)
540 | Obj::Sub(_)
541 | Obj::Mul(_)
542 | Obj::Mod(_)
543 | Obj::Pow(_)
544 | Obj::Max(_)
545 | Obj::Min(_)
546 | Obj::Abs(_),
547 Obj::StandardSet(StandardSet::Z),
548 ) => self.verify_in_fact_arithmetic_expression_in_z(in_fact, verify_state),
549 (
550 Obj::Add(_)
551 | Obj::Sub(_)
552 | Obj::Mul(_)
553 | Obj::Div(_)
554 | Obj::Pow(_)
555 | Obj::Max(_)
556 | Obj::Min(_)
557 | Obj::Abs(_),
558 Obj::StandardSet(StandardSet::Q),
559 ) => self.verify_in_fact_arithmetic_expression_in_q(in_fact, verify_state),
560 (
561 Obj::Add(_)
562 | Obj::Sub(_)
563 | Obj::Mul(_)
564 | Obj::Div(_)
565 | Obj::Mod(_)
566 | Obj::Pow(_)
567 | Obj::Max(_)
568 | Obj::Min(_),
569 Obj::StandardSet(StandardSet::RNeg),
570 ) => self.verify_in_fact_arithmetic_expression_in_standard_negative_set(
571 in_fact,
572 verify_state,
573 StandardSet::RNeg,
574 ),
575 (
576 Obj::Add(_)
577 | Obj::Sub(_)
578 | Obj::Mul(_)
579 | Obj::Div(_)
580 | Obj::Mod(_)
581 | Obj::Pow(_)
582 | Obj::Max(_)
583 | Obj::Min(_),
584 Obj::StandardSet(StandardSet::QNeg),
585 ) => self.verify_in_fact_arithmetic_expression_in_standard_negative_set(
586 in_fact,
587 verify_state,
588 StandardSet::QNeg,
589 ),
590 (
591 Obj::Add(_)
592 | Obj::Sub(_)
593 | Obj::Mul(_)
594 | Obj::Div(_)
595 | Obj::Mod(_)
596 | Obj::Pow(_)
597 | Obj::Max(_)
598 | Obj::Min(_),
599 Obj::StandardSet(StandardSet::ZNeg),
600 ) => self.verify_in_fact_arithmetic_expression_in_standard_negative_set(
601 in_fact,
602 verify_state,
603 StandardSet::ZNeg,
604 ),
605 (
606 Obj::Add(_)
607 | Obj::Sub(_)
608 | Obj::Mul(_)
609 | Obj::Div(_)
610 | Obj::Mod(_)
611 | Obj::Pow(_)
612 | Obj::Max(_)
613 | Obj::Min(_)
614 | Obj::Abs(_)
615 | Obj::Log(_),
616 Obj::StandardSet(StandardSet::R),
617 ) => Ok(arithmetic_obj_in_r_verified_by_builtin_rules_result(
618 in_fact,
619 )),
620 (Obj::Sum(_), Obj::StandardSet(StandardSet::R)) => self
621 .verify_in_fact_sum_or_product_in_r(
622 in_fact,
623 verify_state,
624 "sum: well-defined on an integer range, in R",
625 ),
626 (Obj::Product(_), Obj::StandardSet(StandardSet::R)) => self
627 .verify_in_fact_sum_or_product_in_r(
628 in_fact,
629 verify_state,
630 "product: well-defined on an integer range, in R",
631 ),
632 (Obj::Sum(sum), Obj::StandardSet(StandardSet::Z)) => self
633 .verify_in_fact_sum_or_product_in_z_by_iterand_ret_set(
634 in_fact,
635 sum.func.as_ref(),
636 verify_state,
637 "sum",
638 ),
639 (Obj::Product(product), Obj::StandardSet(StandardSet::Z)) => self
640 .verify_in_fact_sum_or_product_in_z_by_iterand_ret_set(
641 in_fact,
642 product.func.as_ref(),
643 verify_state,
644 "product",
645 ),
646 (Obj::Sum(sum), Obj::StandardSet(StandardSet::Q)) => self
647 .verify_in_fact_sum_or_product_in_q_by_iterand_ret_set(
648 in_fact,
649 sum.func.as_ref(),
650 verify_state,
651 "sum",
652 ),
653 (Obj::Product(product), Obj::StandardSet(StandardSet::Q)) => self
654 .verify_in_fact_sum_or_product_in_q_by_iterand_ret_set(
655 in_fact,
656 product.func.as_ref(),
657 verify_state,
658 "product",
659 ),
660 (Obj::ListSet(list_set), Obj::PowerSet(power_set)) => self
661 .verify_in_fact_list_set_in_power_set_defines_membership(
662 in_fact,
663 list_set,
664 power_set,
665 verify_state,
666 ),
667 (Obj::SetBuilder(set_builder), Obj::PowerSet(power_set)) => self
668 .verify_in_fact_set_builder_in_power_set_via_param_subset(
669 in_fact,
670 set_builder,
671 power_set,
672 verify_state,
673 ),
674 (Obj::Choose(choose), where_is_obj) => {
675 let choose_from = choose.set.clone();
676 let equal_fact = EqualFact::new(
677 *choose_from,
678 where_is_obj.clone(),
679 in_fact.line_file.clone(),
680 )
681 .into();
682 let equal_fact_verify_result =
683 self.verify_atomic_fact(&equal_fact, verify_state)?;
684 if equal_fact_verify_result.is_true() {
685 return Ok((FactualStmtSuccess::new_with_verified_by_builtin_rules_recording_stmt(
686 in_fact.clone().into(),
687 "By ZFC, we can choose an element from a nonempty set whose elements are all nonempty.".to_string(),
688 Vec::new(),
689 )).into());
690 } else {
691 return Ok((StmtUnknown::new()).into());
692 }
693 }
694 (_, Obj::ListSet(list_set)) => self.verify_in_fact_by_equal_to_one_element_in_list_set(
695 in_fact,
696 list_set,
697 verify_state,
698 ),
699 (Obj::AnonymousFn(anon), Obj::FnSet(expected_fn_set)) => self
700 .verify_in_fact_anonymous_fn_signature_matches_fn_set(
701 anon,
702 expected_fn_set,
703 in_fact,
704 verify_state,
705 ),
706 (element, Obj::FnSet(expected_fn_set))
707 if obj_eligible_for_known_objs_in_fn_sets(element) =>
708 {
709 self.verify_in_fact_element_in_fn_set_by_stored_definition(
710 element,
711 expected_fn_set,
712 in_fact,
713 )
714 }
715 (_, Obj::FamilyObj(family_ty)) => {
716 self.verify_obj_satisfies_family(in_fact.element.clone(), family_ty, verify_state)
717 }
718 (Obj::FiniteSeqListObj(list), Obj::FiniteSeqSet(fs)) => {
719 let lf = in_fact.line_file.clone();
720 let len_obj: Obj = Number::new(list.objs.len().to_string()).into();
721 let len_eq_n: AtomicFact =
722 EqualFact::new(len_obj, (*fs.n).clone(), lf.clone()).into();
723 if !self.verify_atomic_fact(&len_eq_n, verify_state)?.is_true() {
724 return Ok((StmtUnknown::new()).into());
725 }
726 for o in list.objs.iter() {
727 let f: AtomicFact =
728 InFact::new((**o).clone(), (*fs.set).clone(), lf.clone()).into();
729 if !self.non_equational_atomic_fact_holds_by_full_verify_pipeline(
730 &f,
731 verify_state,
732 )? {
733 return Ok((StmtUnknown::new()).into());
734 }
735 }
736 Ok(number_in_set_verified_by_builtin_rules_result(
737 in_fact,
738 "finite_seq list: length equals n and each entry in co-domain",
739 ))
740 }
741 (Obj::MatrixListObj(list), Obj::MatrixSet(ms)) => {
742 let lf = in_fact.line_file.clone();
743 let n_rows_obj: Obj = Number::new(list.rows.len().to_string()).into();
744 let row_eq: AtomicFact =
745 EqualFact::new(n_rows_obj, (*ms.row_len).clone(), lf.clone()).into();
746 if !self.verify_atomic_fact(&row_eq, verify_state)?.is_true() {
747 return Ok((StmtUnknown::new()).into());
748 }
749 for row in list.rows.iter() {
750 let n_col_obj: Obj = Number::new(row.len().to_string()).into();
751 let col_eq: AtomicFact =
752 EqualFact::new(n_col_obj, (*ms.col_len).clone(), lf.clone()).into();
753 if !self.verify_atomic_fact(&col_eq, verify_state)?.is_true() {
754 return Ok((StmtUnknown::new()).into());
755 }
756 for o in row.iter() {
757 let f: AtomicFact =
758 InFact::new((**o).clone(), (*ms.set).clone(), lf.clone()).into();
759 if !self.non_equational_atomic_fact_holds_by_full_verify_pipeline(
760 &f,
761 verify_state,
762 )? {
763 return Ok((StmtUnknown::new()).into());
764 }
765 }
766 }
767 Ok(number_in_set_verified_by_builtin_rules_result(
768 in_fact,
769 "matrix literal: shape matches matrix(...) and each entry in co-domain",
770 ))
771 }
772 (_, Obj::FiniteSeqSet(fs)) => {
773 let fn_set = self.finite_seq_set_to_fn_set(fs, in_fact.line_file.clone());
774 let expanded = InFact::new(
775 in_fact.element.clone(),
776 fn_set.into(),
777 in_fact.line_file.clone(),
778 );
779 self.verify_atomic_fact(&expanded.into(), verify_state)
780 }
781 (_, Obj::SeqSet(ss)) => {
782 let fn_set = self.seq_set_to_fn_set(ss, in_fact.line_file.clone());
783 let expanded = InFact::new(
784 in_fact.element.clone(),
785 fn_set.into(),
786 in_fact.line_file.clone(),
787 );
788 self.verify_atomic_fact(&expanded.into(), verify_state)
789 }
790 (_, Obj::MatrixSet(ms)) => {
791 let fn_set = self.matrix_set_to_fn_set(ms, in_fact.line_file.clone());
792 let expanded = InFact::new(
793 in_fact.element.clone(),
794 fn_set.into(),
795 in_fact.line_file.clone(),
796 );
797 self.verify_atomic_fact(&expanded.into(), verify_state)
798 }
799 (_, target_set_obj) => {
800 if let Obj::FnObj(fn_obj) = &in_fact.element {
801 let fn_try = self.verify_in_fact_fn_application_in_typed_return_set(
802 fn_obj,
803 in_fact,
804 verify_state,
805 )?;
806 if fn_try.is_true() {
807 return Ok(fn_try);
808 }
809 }
810 self.verify_in_fact_by_known_standard_subset_membership(in_fact, target_set_obj)
811 }
812 }
813 }
814
815 fn verify_in_fact_add_in_n_from_summands_in_n(
818 &mut self,
819 in_fact: &InFact,
820 add: &Add,
821 verify_state: &VerifyState,
822 ) -> Result<StmtResult, RuntimeError> {
823 if let Some(evaluated_number) = in_fact.element.evaluate_to_normalized_decimal_number() {
824 return Ok(builtin_in_fact_result_for_evaluated_number_in_standard_set(
825 in_fact,
826 &evaluated_number,
827 &StandardSet::N,
828 ));
829 }
830 let n: Obj = StandardSet::N.into();
831 let lf = in_fact.line_file.clone();
832 let f_left: AtomicFact =
833 InFact::new(add.left.as_ref().clone(), n.clone(), lf.clone()).into();
834 let f_right: AtomicFact = InFact::new(add.right.as_ref().clone(), n, lf.clone()).into();
835 let r_left = self.verify_non_equational_atomic_fact(&f_left, verify_state, true)?;
836 if !r_left.is_true() {
837 return Ok((StmtUnknown::new()).into());
838 }
839 let r_right = self.verify_non_equational_atomic_fact(&f_right, verify_state, true)?;
840 if !r_right.is_true() {
841 return Ok((StmtUnknown::new()).into());
842 }
843 Ok(
844 FactualStmtSuccess::new_with_verified_by_builtin_rules_recording_stmt(
845 in_fact.clone().into(),
846 "N: a + b from a in N and b in N".to_string(),
847 vec![r_left, r_right],
848 )
849 .into(),
850 )
851 }
852
853 fn verify_in_fact_mul_in_n_from_factors_in_n(
856 &mut self,
857 in_fact: &InFact,
858 mul: &Mul,
859 verify_state: &VerifyState,
860 ) -> Result<StmtResult, RuntimeError> {
861 if let Some(evaluated_number) = in_fact.element.evaluate_to_normalized_decimal_number() {
862 return Ok(builtin_in_fact_result_for_evaluated_number_in_standard_set(
863 in_fact,
864 &evaluated_number,
865 &StandardSet::N,
866 ));
867 }
868 let n: Obj = StandardSet::N.into();
869 let lf = in_fact.line_file.clone();
870 let f_left: AtomicFact =
871 InFact::new(mul.left.as_ref().clone(), n.clone(), lf.clone()).into();
872 let f_right: AtomicFact = InFact::new(mul.right.as_ref().clone(), n, lf.clone()).into();
873 let r_left = self.verify_non_equational_atomic_fact(&f_left, verify_state, true)?;
874 if !r_left.is_true() {
875 return Ok((StmtUnknown::new()).into());
876 }
877 let r_right = self.verify_non_equational_atomic_fact(&f_right, verify_state, true)?;
878 if !r_right.is_true() {
879 return Ok((StmtUnknown::new()).into());
880 }
881 Ok(
882 FactualStmtSuccess::new_with_verified_by_builtin_rules_recording_stmt(
883 in_fact.clone().into(),
884 "N: a * b from a in N and b in N".to_string(),
885 vec![r_left, r_right],
886 )
887 .into(),
888 )
889 }
890
891 fn verify_in_fact_add_in_n_pos_from_n_pos_and_n(
895 &mut self,
896 in_fact: &InFact,
897 add: &Add,
898 verify_state: &VerifyState,
899 ) -> Result<StmtResult, RuntimeError> {
900 if let Some(evaluated_number) = in_fact.element.evaluate_to_normalized_decimal_number() {
901 return Ok(builtin_in_fact_result_for_evaluated_number_in_standard_set(
902 in_fact,
903 &evaluated_number,
904 &StandardSet::NPos,
905 ));
906 }
907 let n_pos: Obj = StandardSet::NPos.into();
908 let n: Obj = StandardSet::N.into();
909 let lf = in_fact.line_file.clone();
910
911 let left_n_pos: AtomicFact =
912 InFact::new(add.left.as_ref().clone(), n_pos.clone(), lf.clone()).into();
913 let right_n_pos_for_pair: AtomicFact =
914 InFact::new(add.right.as_ref().clone(), n_pos.clone(), lf.clone()).into();
915 let r_left_n_pos_for_pair =
916 self.verify_non_equational_atomic_fact(&left_n_pos, verify_state, true)?;
917 if r_left_n_pos_for_pair.is_true() {
918 let r_right_n_pos_for_pair =
919 self.verify_non_equational_atomic_fact(&right_n_pos_for_pair, verify_state, true)?;
920 if r_right_n_pos_for_pair.is_true() {
921 return Ok(
922 FactualStmtSuccess::new_with_verified_by_builtin_rules_recording_stmt(
923 in_fact.clone().into(),
924 "N_pos: a + b from a in N_pos and b in N_pos".to_string(),
925 vec![r_left_n_pos_for_pair, r_right_n_pos_for_pair],
926 )
927 .into(),
928 );
929 }
930 }
931
932 let right_n: AtomicFact =
933 InFact::new(add.right.as_ref().clone(), n.clone(), lf.clone()).into();
934 let r_left_n_pos =
935 self.verify_non_equational_atomic_fact(&left_n_pos, verify_state, true)?;
936 if r_left_n_pos.is_true() {
937 let r_right_n = self.verify_non_equational_atomic_fact(&right_n, verify_state, true)?;
938 if r_right_n.is_true() {
939 return Ok(
940 FactualStmtSuccess::new_with_verified_by_builtin_rules_recording_stmt(
941 in_fact.clone().into(),
942 "N_pos: a + b from a in N_pos and b in N".to_string(),
943 vec![r_left_n_pos, r_right_n],
944 )
945 .into(),
946 );
947 }
948 }
949
950 let left_n: AtomicFact =
951 InFact::new(add.left.as_ref().clone(), n.clone(), lf.clone()).into();
952 let right_n_pos: AtomicFact =
953 InFact::new(add.right.as_ref().clone(), n_pos, lf.clone()).into();
954 let r_left_n = self.verify_non_equational_atomic_fact(&left_n, verify_state, true)?;
955 if !r_left_n.is_true() {
956 return Ok((StmtUnknown::new()).into());
957 }
958 let r_right_n_pos =
959 self.verify_non_equational_atomic_fact(&right_n_pos, verify_state, true)?;
960 if !r_right_n_pos.is_true() {
961 return Ok((StmtUnknown::new()).into());
962 }
963 Ok(
964 FactualStmtSuccess::new_with_verified_by_builtin_rules_recording_stmt(
965 in_fact.clone().into(),
966 "N_pos: a + b from a in N and b in N_pos".to_string(),
967 vec![r_left_n, r_right_n_pos],
968 )
969 .into(),
970 )
971 }
972
973 fn verify_in_fact_mul_in_n_pos_from_factors_in_n_pos(
976 &mut self,
977 in_fact: &InFact,
978 mul: &Mul,
979 verify_state: &VerifyState,
980 ) -> Result<StmtResult, RuntimeError> {
981 if let Some(evaluated_number) = in_fact.element.evaluate_to_normalized_decimal_number() {
982 return Ok(builtin_in_fact_result_for_evaluated_number_in_standard_set(
983 in_fact,
984 &evaluated_number,
985 &StandardSet::NPos,
986 ));
987 }
988 let n_pos: Obj = StandardSet::NPos.into();
989 let lf = in_fact.line_file.clone();
990 let f_left: AtomicFact =
991 InFact::new(mul.left.as_ref().clone(), n_pos.clone(), lf.clone()).into();
992 let f_right: AtomicFact = InFact::new(mul.right.as_ref().clone(), n_pos, lf.clone()).into();
993 let r_left = self.verify_non_equational_atomic_fact(&f_left, verify_state, true)?;
994 if !r_left.is_true() {
995 return Ok((StmtUnknown::new()).into());
996 }
997 let r_right = self.verify_non_equational_atomic_fact(&f_right, verify_state, true)?;
998 if !r_right.is_true() {
999 return Ok((StmtUnknown::new()).into());
1000 }
1001 Ok(
1002 FactualStmtSuccess::new_with_verified_by_builtin_rules_recording_stmt(
1003 in_fact.clone().into(),
1004 "N_pos: a * b from a in N_pos and b in N_pos".to_string(),
1005 vec![r_left, r_right],
1006 )
1007 .into(),
1008 )
1009 }
1010
1011 fn verify_in_fact_n_pos_by_zero_less_and_in_z_or_n(
1013 &mut self,
1014 in_fact: &InFact,
1015 verify_state: &VerifyState,
1016 ) -> Result<StmtResult, RuntimeError> {
1017 let elem = &in_fact.element;
1018 let lf = in_fact.line_file.clone();
1019 let zero: Obj = Number::new("0".to_string()).into();
1020 let zero_lt_elem = LessFact::new(zero, elem.clone(), lf.clone()).into();
1021 if !self
1022 .non_equational_atomic_fact_holds_by_full_verify_pipeline(&zero_lt_elem, verify_state)?
1023 {
1024 return Ok((StmtUnknown::new()).into());
1025 }
1026
1027 let in_z = InFact::new(elem.clone(), StandardSet::Z.into(), lf.clone()).into();
1028 if self.non_equational_atomic_fact_holds_by_full_verify_pipeline(&in_z, verify_state)? {
1029 return Ok(number_in_set_verified_by_builtin_rules_result(
1030 in_fact,
1031 "N_pos: 0 < x and x in Z",
1032 ));
1033 }
1034
1035 let in_n = InFact::new(elem.clone(), StandardSet::N.into(), lf.clone()).into();
1036 if self.non_equational_atomic_fact_holds_by_full_verify_pipeline(&in_n, verify_state)? {
1037 return Ok(number_in_set_verified_by_builtin_rules_result(
1038 in_fact,
1039 "N_pos: 0 < x and x in N",
1040 ));
1041 }
1042
1043 Ok((StmtUnknown::new()).into())
1044 }
1045
1046 fn verify_in_fact_closed_range_by_order_bounds(
1047 &mut self,
1048 in_fact: &InFact,
1049 closed_range: &ClosedRange,
1050 verify_state: &VerifyState,
1051 ) -> Result<StmtResult, RuntimeError> {
1052 let elem = &in_fact.element;
1053 let lf = in_fact.line_file.clone();
1054 if !self.order_lower_bound_from_literals(
1055 elem,
1056 closed_range.start.as_ref(),
1057 &lf,
1058 verify_state,
1059 )? {
1060 return Ok((StmtUnknown::new()).into());
1061 }
1062 if !self.order_upper_bound_closed_from_literals(
1063 elem,
1064 closed_range.end.as_ref(),
1065 &lf,
1066 verify_state,
1067 )? {
1068 return Ok((StmtUnknown::new()).into());
1069 }
1070 Ok(number_in_set_verified_by_builtin_rules_result(
1071 in_fact,
1072 "in closed_range: a <= i and i <= b",
1073 ))
1074 }
1075
1076 fn verify_in_fact_open_range_by_order_bounds(
1077 &mut self,
1078 in_fact: &InFact,
1079 range: &Range,
1080 verify_state: &VerifyState,
1081 ) -> Result<StmtResult, RuntimeError> {
1082 let elem = &in_fact.element;
1083 let lf = in_fact.line_file.clone();
1084 if !self.order_lower_bound_from_literals(elem, range.start.as_ref(), &lf, verify_state)? {
1085 return Ok((StmtUnknown::new()).into());
1086 }
1087 if !self.order_upper_bound_open_from_literals(
1088 elem,
1089 range.end.as_ref(),
1090 &lf,
1091 verify_state,
1092 )? {
1093 return Ok((StmtUnknown::new()).into());
1094 }
1095 Ok(number_in_set_verified_by_builtin_rules_result(
1096 in_fact,
1097 "in range: a <= i and i < b",
1098 ))
1099 }
1100
1101 fn order_lower_bound_from_literals(
1104 &mut self,
1105 elem: &Obj,
1106 lower: &Obj,
1107 lf: &LineFile,
1108 verify_state: &VerifyState,
1109 ) -> Result<bool, RuntimeError> {
1110 let weak: AtomicFact = LessEqualFact::new(lower.clone(), elem.clone(), lf.clone()).into();
1111 if self.non_equational_atomic_fact_holds_by_full_verify_pipeline(&weak, verify_state)? {
1112 return Ok(true);
1113 }
1114 let in_z: AtomicFact = InFact::new(elem.clone(), StandardSet::Z.into(), lf.clone()).into();
1115 if !self.non_equational_atomic_fact_holds_by_full_verify_pipeline(&in_z, verify_state)? {
1116 return Ok(false);
1117 }
1118 let Some(lower_num) = self.resolve_obj_to_number_resolved(lower) else {
1119 return Ok(false);
1120 };
1121 if !is_integer_after_simplification(&lower_num) {
1122 return Ok(false);
1123 }
1124 let pred = Obj::Sub(Sub::new(lower.clone(), Number::new("1".to_string()).into()));
1125 let Some(pred_n) = pred.evaluate_to_normalized_decimal_number() else {
1126 return Ok(false);
1127 };
1128 let strict: AtomicFact = LessFact::new(pred_n.into(), elem.clone(), lf.clone()).into();
1129 self.non_equational_atomic_fact_holds_by_full_verify_pipeline(&strict, verify_state)
1130 }
1131
1132 fn order_upper_bound_open_from_literals(
1135 &mut self,
1136 elem: &Obj,
1137 upper: &Obj,
1138 lf: &LineFile,
1139 verify_state: &VerifyState,
1140 ) -> Result<bool, RuntimeError> {
1141 let strict: AtomicFact = LessFact::new(elem.clone(), upper.clone(), lf.clone()).into();
1142 if self.non_equational_atomic_fact_holds_by_full_verify_pipeline(&strict, verify_state)? {
1143 return Ok(true);
1144 }
1145 let in_z: AtomicFact = InFact::new(elem.clone(), StandardSet::Z.into(), lf.clone()).into();
1146 if !self.non_equational_atomic_fact_holds_by_full_verify_pipeline(&in_z, verify_state)? {
1147 return Ok(false);
1148 }
1149 let Some(upper_num) = self.resolve_obj_to_number_resolved(upper) else {
1150 return Ok(false);
1151 };
1152 if !is_integer_after_simplification(&upper_num) {
1153 return Ok(false);
1154 }
1155 let upper_minus_one =
1156 Obj::Sub(Sub::new(upper.clone(), Number::new("1".to_string()).into()));
1157 let Some(um) = upper_minus_one.evaluate_to_normalized_decimal_number() else {
1158 return Ok(false);
1159 };
1160 let weak: AtomicFact = LessEqualFact::new(elem.clone(), um.into(), lf.clone()).into();
1161 self.non_equational_atomic_fact_holds_by_full_verify_pipeline(&weak, verify_state)
1162 }
1163
1164 fn order_upper_bound_closed_from_literals(
1166 &mut self,
1167 elem: &Obj,
1168 upper: &Obj,
1169 lf: &LineFile,
1170 verify_state: &VerifyState,
1171 ) -> Result<bool, RuntimeError> {
1172 let weak: AtomicFact = LessEqualFact::new(elem.clone(), upper.clone(), lf.clone()).into();
1173 if self.non_equational_atomic_fact_holds_by_full_verify_pipeline(&weak, verify_state)? {
1174 return Ok(true);
1175 }
1176 let in_z: AtomicFact = InFact::new(elem.clone(), StandardSet::Z.into(), lf.clone()).into();
1177 if !self.non_equational_atomic_fact_holds_by_full_verify_pipeline(&in_z, verify_state)? {
1178 return Ok(false);
1179 }
1180 let Some(upper_num) = self.resolve_obj_to_number_resolved(upper) else {
1181 return Ok(false);
1182 };
1183 if !is_integer_after_simplification(&upper_num) {
1184 return Ok(false);
1185 }
1186 let hi_plus_one = Obj::Add(Add::new(upper.clone(), Number::new("1".to_string()).into()));
1187 let Some(hp) = hi_plus_one.evaluate_to_normalized_decimal_number() else {
1188 return Ok(false);
1189 };
1190 let strict: AtomicFact = LessFact::new(elem.clone(), hp.into(), lf.clone()).into();
1191 self.non_equational_atomic_fact_holds_by_full_verify_pipeline(&strict, verify_state)
1192 }
1193
1194 fn verify_in_fact_arithmetic_expression_in_z(
1197 &mut self,
1198 in_fact: &InFact,
1199 verify_state: &VerifyState,
1200 ) -> Result<StmtResult, RuntimeError> {
1201 if let Some(evaluated_number) = in_fact.element.evaluate_to_normalized_decimal_number() {
1202 return Ok(builtin_in_fact_result_for_evaluated_number_in_standard_set(
1203 in_fact,
1204 &evaluated_number,
1205 &StandardSet::Z,
1206 ));
1207 }
1208 let z_obj: Obj = StandardSet::Z.into();
1209 let lf = in_fact.line_file.clone();
1210
1211 let mut require_in_z = |o: &Obj| -> Result<bool, RuntimeError> {
1212 let f = InFact::new(o.clone(), z_obj.clone(), lf.clone()).into();
1213 self.non_equational_atomic_fact_holds_by_full_verify_pipeline(&f, verify_state)
1214 };
1215
1216 let ok = match &in_fact.element {
1217 Obj::Add(a) => require_in_z(&a.left)? && require_in_z(&a.right)?,
1218 Obj::Sub(s) => require_in_z(&s.left)? && require_in_z(&s.right)?,
1219 Obj::Mul(m) => require_in_z(&m.left)? && require_in_z(&m.right)?,
1220 Obj::Mod(m) => require_in_z(&m.left)? && require_in_z(&m.right)?,
1221 Obj::Pow(p) => require_in_z(&p.base)? && require_in_z(&p.exponent)?,
1222 Obj::Max(m) => require_in_z(&m.left)? && require_in_z(&m.right)?,
1223 Obj::Min(m) => require_in_z(&m.left)? && require_in_z(&m.right)?,
1224 Obj::Abs(a) => require_in_z(a.arg.as_ref())?,
1225 _ => false,
1226 };
1227
1228 if !ok {
1229 return Ok((StmtUnknown::new()).into());
1230 }
1231
1232 Ok(
1233 (FactualStmtSuccess::new_with_verified_by_builtin_rules_recording_stmt(
1234 in_fact.clone().into(),
1235 "Z closure: operands in Z".to_string(),
1236 Vec::new(),
1237 ))
1238 .into(),
1239 )
1240 }
1241
1242 fn verify_in_fact_arithmetic_expression_in_q(
1245 &mut self,
1246 in_fact: &InFact,
1247 verify_state: &VerifyState,
1248 ) -> Result<StmtResult, RuntimeError> {
1249 if let Some(evaluated_number) = in_fact.element.evaluate_to_normalized_decimal_number() {
1250 return Ok(builtin_in_fact_result_for_evaluated_number_in_standard_set(
1251 in_fact,
1252 &evaluated_number,
1253 &StandardSet::Q,
1254 ));
1255 }
1256 let q_obj: Obj = StandardSet::Q.into();
1257 let z_obj: Obj = StandardSet::Z.into();
1258 let lf = in_fact.line_file.clone();
1259
1260 let in_q = |slf: &mut Self, o: &Obj| -> Result<bool, RuntimeError> {
1261 let f = InFact::new(o.clone(), q_obj.clone(), lf.clone()).into();
1262 slf.non_equational_atomic_fact_holds_by_full_verify_pipeline(&f, verify_state)
1263 };
1264 let in_z = |slf: &mut Self, o: &Obj| -> Result<bool, RuntimeError> {
1265 let f = InFact::new(o.clone(), z_obj.clone(), lf.clone()).into();
1266 slf.non_equational_atomic_fact_holds_by_full_verify_pipeline(&f, verify_state)
1267 };
1268
1269 let ok = match &in_fact.element {
1270 Obj::Add(a) => in_q(self, &a.left)? && in_q(self, &a.right)?,
1271 Obj::Sub(s) => in_q(self, &s.left)? && in_q(self, &s.right)?,
1272 Obj::Mul(m) => in_q(self, &m.left)? && in_q(self, &m.right)?,
1273 Obj::Div(d) => in_q(self, &d.left)? && in_q(self, &d.right)?,
1274 Obj::Pow(p) => in_q(self, &p.base)? && in_z(self, &p.exponent)?,
1275 Obj::Max(m) => in_q(self, &m.left)? && in_q(self, &m.right)?,
1276 Obj::Min(m) => in_q(self, &m.left)? && in_q(self, &m.right)?,
1277 Obj::Abs(a) => in_q(self, a.arg.as_ref())?,
1278 _ => false,
1279 };
1280
1281 if !ok {
1282 return Ok((StmtUnknown::new()).into());
1283 }
1284
1285 Ok(
1286 (FactualStmtSuccess::new_with_verified_by_builtin_rules_recording_stmt(
1287 in_fact.clone().into(),
1288 "Q closure: +-*/ operands in Q; pow base in Q and exponent in Z".to_string(),
1289 Vec::new(),
1290 ))
1291 .into(),
1292 )
1293 }
1294
1295 fn verify_in_fact_arithmetic_expression_in_standard_negative_set(
1296 &mut self,
1297 in_fact: &InFact,
1298 verify_state: &VerifyState,
1299 target_negative_standard_set: StandardSet,
1300 ) -> Result<StmtResult, RuntimeError> {
1301 if let Some(evaluated_number) = in_fact.element.evaluate_to_normalized_decimal_number() {
1302 return Ok(builtin_in_fact_result_for_evaluated_number_in_standard_set(
1303 in_fact,
1304 &evaluated_number,
1305 &target_negative_standard_set,
1306 ));
1307 }
1308 let mul = match &in_fact.element {
1309 Obj::Mul(mul) => mul,
1310 _ => return Ok((StmtUnknown::new()).into()),
1311 };
1312 let product_in_r_fact = InFact::new(
1313 in_fact.element.clone(),
1314 StandardSet::R.into(),
1315 in_fact.line_file.clone(),
1316 )
1317 .into();
1318 if !self.non_equational_atomic_fact_holds_by_full_verify_pipeline(
1319 &product_in_r_fact,
1320 verify_state,
1321 )? {
1322 return Ok((StmtUnknown::new()).into());
1323 }
1324 if !self
1325 .mul_product_negative_when_factors_have_strict_opposite_sign_by_non_equational_verify(
1326 &mul.left,
1327 &mul.right,
1328 in_fact.line_file.clone(),
1329 verify_state,
1330 )?
1331 {
1332 return Ok((StmtUnknown::new()).into());
1333 }
1334 match target_negative_standard_set {
1335 StandardSet::RNeg => Ok(
1336 (FactualStmtSuccess::new_with_verified_by_builtin_rules_recording_stmt(
1337 in_fact.clone().into(),
1338 "mul_opposite_signs_product_in_R_neg".to_string(),
1339 Vec::new(),
1340 ))
1341 .into(),
1342 ),
1343 StandardSet::QNeg => {
1344 let product_in_q_fact = InFact::new(
1345 in_fact.element.clone(),
1346 StandardSet::Q.into(),
1347 in_fact.line_file.clone(),
1348 )
1349 .into();
1350 if self.non_equational_atomic_fact_holds_by_full_verify_pipeline(
1351 &product_in_q_fact,
1352 verify_state,
1353 )? {
1354 Ok(
1355 (FactualStmtSuccess::new_with_verified_by_builtin_rules_recording_stmt(
1356 in_fact.clone().into(),
1357 "mul_opposite_signs_product_in_Q_neg".to_string(),
1358 Vec::new(),
1359 ))
1360 .into(),
1361 )
1362 } else {
1363 Ok((StmtUnknown::new()).into())
1364 }
1365 }
1366 StandardSet::ZNeg => {
1367 let product_in_z_fact = InFact::new(
1368 in_fact.element.clone(),
1369 StandardSet::Z.into(),
1370 in_fact.line_file.clone(),
1371 )
1372 .into();
1373 if self.non_equational_atomic_fact_holds_by_full_verify_pipeline(
1374 &product_in_z_fact,
1375 verify_state,
1376 )? {
1377 Ok(
1378 (FactualStmtSuccess::new_with_verified_by_builtin_rules_recording_stmt(
1379 in_fact.clone().into(),
1380 "mul_opposite_signs_product_in_Z_neg".to_string(),
1381 Vec::new(),
1382 ))
1383 .into(),
1384 )
1385 } else {
1386 Ok((StmtUnknown::new()).into())
1387 }
1388 }
1389 _ => Ok((StmtUnknown::new()).into()),
1390 }
1391 }
1392
1393 fn verify_in_fact_set_builder_in_power_set_via_param_subset(
1396 &mut self,
1397 in_fact: &InFact,
1398 set_builder: &SetBuilder,
1399 power_set: &PowerSet,
1400 verify_state: &VerifyState,
1401 ) -> Result<StmtResult, RuntimeError> {
1402 let base_set = power_set.set.as_ref();
1403 let subset_fact = SubsetFact::new(
1404 (*set_builder.param_set).clone(),
1405 base_set.clone(),
1406 in_fact.line_file.clone(),
1407 )
1408 .into();
1409 let verify_subset_result = self.verify_atomic_fact(&subset_fact, verify_state)?;
1410 if !verify_subset_result.is_true() {
1411 return Ok((StmtUnknown::new()).into());
1412 }
1413 let mut infer_result = InferResult::new();
1414 match verify_subset_result {
1415 StmtResult::FactualStmtSuccess(factual_success) => {
1416 infer_result.new_infer_result_inside(factual_success.infers.clone());
1417 }
1418 StmtResult::NonFactualStmtSuccess(non_factual_success) => {
1419 infer_result.new_infer_result_inside(non_factual_success.infers.clone());
1420 }
1421 StmtResult::StmtUnknown(_) => {
1422 return Ok((StmtUnknown::new()).into());
1423 }
1424 }
1425 let stmt = in_fact.clone().into();
1426 infer_result.new_fact(&stmt);
1427 Ok((FactualStmtSuccess::new_with_verified_by_builtin_rules(
1428 stmt,
1429 infer_result,
1430 VerifiedByResult::BuiltinRules(
1431 "set_builder in power_set: param_set subset of base implies builder defines a subset of base"
1432 .to_string(),
1433 ),
1434 ))
1435 .into())
1436 }
1437
1438 fn verify_in_fact_list_set_in_power_set_defines_membership(
1439 &mut self,
1440 in_fact: &InFact,
1441 list_set: &ListSet,
1442 power_set: &PowerSet,
1443 verify_state: &VerifyState,
1444 ) -> Result<StmtResult, RuntimeError> {
1445 let base_set = power_set.set.as_ref();
1446 let mut infer_result = InferResult::new();
1447 for element_box in list_set.list.iter() {
1448 let element_obj = *element_box.clone();
1449 let element_in_base_fact =
1450 InFact::new(element_obj, base_set.clone(), in_fact.line_file.clone()).into();
1451 let verify_one_element_result =
1452 self.verify_atomic_fact(&element_in_base_fact, verify_state)?;
1453 if !verify_one_element_result.is_true() {
1454 return Ok((StmtUnknown::new()).into());
1455 }
1456 match verify_one_element_result {
1457 StmtResult::FactualStmtSuccess(factual_success) => {
1458 infer_result.new_infer_result_inside(factual_success.infers.clone());
1459 }
1460 StmtResult::NonFactualStmtSuccess(non_factual_success) => {
1461 infer_result.new_infer_result_inside(non_factual_success.infers.clone());
1462 }
1463 StmtResult::StmtUnknown(_) => {
1464 return Ok((StmtUnknown::new()).into());
1465 }
1466 }
1467 }
1468 let stmt = in_fact.clone().into();
1469 infer_result.new_fact(&stmt);
1470 Ok((FactualStmtSuccess::new_with_verified_by_builtin_rules(
1471 stmt,
1472 infer_result,
1473 VerifiedByResult::BuiltinRules(
1474 "list_set in power_set: each element is in the base set".to_string(),
1475 ),
1476 ))
1477 .into())
1478 }
1479
1480 fn verify_in_fact_by_equal_to_one_element_in_list_set(
1481 &mut self,
1482 in_fact: &InFact,
1483 list_set: &ListSet,
1484 verify_state: &VerifyState,
1485 ) -> Result<StmtResult, RuntimeError> {
1486 for current_element_in_list_set in list_set.list.iter() {
1487 let equal_fact = EqualFact::new(
1488 in_fact.element.clone(),
1489 *current_element_in_list_set.clone(),
1490 in_fact.line_file.clone(),
1491 )
1492 .into();
1493 let equal_fact_verify_result = self.verify_atomic_fact(&equal_fact, verify_state)?;
1494 if equal_fact_verify_result.is_true() {
1495 return Ok(
1496 (FactualStmtSuccess::new_with_verified_by_builtin_rules_recording_stmt(
1497 in_fact.clone().into(),
1498 format!(
1499 "{} equals one element in list_set {}",
1500 in_fact.element, in_fact.set
1501 ),
1502 Vec::new(),
1503 ))
1504 .into(),
1505 );
1506 }
1507 }
1508 Ok((StmtUnknown::new()).into())
1509 }
1510
1511 fn standard_subset_set_objs_for_target_set(target_set_obj: &Obj) -> Option<Vec<Obj>> {
1512 match target_set_obj {
1513 Obj::StandardSet(StandardSet::NPos) => Some(vec![]),
1514 Obj::StandardSet(StandardSet::N) => Some(vec![StandardSet::NPos.into()]),
1515 Obj::StandardSet(StandardSet::ZNeg) => Some(vec![]),
1516 Obj::StandardSet(StandardSet::ZNz) => {
1517 Some(vec![StandardSet::NPos.into(), StandardSet::ZNeg.into()])
1518 }
1519 Obj::StandardSet(StandardSet::Z) => Some(vec![
1520 StandardSet::NPos.into(),
1521 StandardSet::N.into(),
1522 StandardSet::ZNeg.into(),
1523 StandardSet::ZNz.into(),
1524 ]),
1525 Obj::StandardSet(StandardSet::QPos) => Some(vec![StandardSet::NPos.into()]),
1526 Obj::StandardSet(StandardSet::QNeg) => Some(vec![StandardSet::ZNeg.into()]),
1527 Obj::StandardSet(StandardSet::QNz) => Some(vec![
1528 StandardSet::NPos.into(),
1529 StandardSet::ZNeg.into(),
1530 StandardSet::ZNz.into(),
1531 StandardSet::QPos.into(),
1532 StandardSet::QNeg.into(),
1533 ]),
1534 Obj::StandardSet(StandardSet::Q) => Some(vec![
1535 StandardSet::NPos.into(),
1536 StandardSet::N.into(),
1537 StandardSet::ZNeg.into(),
1538 StandardSet::ZNz.into(),
1539 StandardSet::Z.into(),
1540 StandardSet::QPos.into(),
1541 StandardSet::QNeg.into(),
1542 StandardSet::QNz.into(),
1543 ]),
1544 Obj::StandardSet(StandardSet::RPos) => {
1545 Some(vec![StandardSet::NPos.into(), StandardSet::QPos.into()])
1546 }
1547 Obj::StandardSet(StandardSet::RNeg) => {
1548 Some(vec![StandardSet::ZNeg.into(), StandardSet::QNeg.into()])
1549 }
1550 Obj::StandardSet(StandardSet::RNz) => Some(vec![
1551 StandardSet::NPos.into(),
1552 StandardSet::ZNeg.into(),
1553 StandardSet::ZNz.into(),
1554 StandardSet::QPos.into(),
1555 StandardSet::QNeg.into(),
1556 StandardSet::QNz.into(),
1557 StandardSet::RPos.into(),
1558 StandardSet::RNeg.into(),
1559 ]),
1560 Obj::StandardSet(StandardSet::R) => Some(vec![
1561 StandardSet::NPos.into(),
1562 StandardSet::N.into(),
1563 StandardSet::ZNeg.into(),
1564 StandardSet::ZNz.into(),
1565 StandardSet::Z.into(),
1566 StandardSet::QPos.into(),
1567 StandardSet::QNeg.into(),
1568 StandardSet::QNz.into(),
1569 StandardSet::Q.into(),
1570 StandardSet::RPos.into(),
1571 StandardSet::RNeg.into(),
1572 StandardSet::RNz.into(),
1573 ]),
1574 _ => None,
1575 }
1576 }
1577
1578 fn verify_in_fact_element_in_fn_set_by_stored_definition(
1580 &mut self,
1581 element: &Obj,
1582 expected_fn_set: &FnSet,
1583 in_fact: &InFact,
1584 ) -> Result<StmtResult, RuntimeError> {
1585 let Some(stored_fn_set) = self.get_cloned_object_in_fn_set(element) else {
1586 return Ok((StmtUnknown::new()).into());
1587 };
1588 if stored_fn_set.to_string() == expected_fn_set.to_string() {
1589 return Ok(
1590 (FactualStmtSuccess::new_with_verified_by_builtin_rules_recording_stmt(
1591 in_fact.clone().into(),
1592 "fn membership: stored fn signature matches RHS".to_string(),
1593 Vec::new(),
1594 ))
1595 .into(),
1596 );
1597 }
1598 let flat_stored =
1599 ParamGroupWithSet::collect_param_names(&stored_fn_set.params_def_with_set);
1600 let flat_expected =
1601 ParamGroupWithSet::collect_param_names(&expected_fn_set.body.params_def_with_set);
1602 if flat_stored.len() != flat_expected.len() {
1603 return Ok((StmtUnknown::new()).into());
1604 }
1605 let shared_names = self.generate_random_unused_names(flat_stored.len());
1606 let stored_norm =
1607 self.fn_set_alpha_renamed_for_display_compare(&stored_fn_set, &shared_names)?;
1608 let expected_norm =
1609 self.fn_set_alpha_renamed_for_display_compare(&expected_fn_set.body, &shared_names)?;
1610 if stored_norm.to_string() == expected_norm.to_string() {
1611 return Ok(
1612 (FactualStmtSuccess::new_with_verified_by_builtin_rules_recording_stmt(
1613 in_fact.clone().into(),
1614 "fn membership: stored fn signature matches RHS (alpha-renamed parameters)"
1615 .to_string(),
1616 Vec::new(),
1617 ))
1618 .into(),
1619 );
1620 }
1621 Ok((StmtUnknown::new()).into())
1622 }
1623
1624 fn verify_in_fact_anonymous_fn_signature_matches_fn_set(
1628 &mut self,
1629 anon: &AnonymousFn,
1630 expected_fn_set: &FnSet,
1631 in_fact: &InFact,
1632 verify_state: &VerifyState,
1633 ) -> Result<StmtResult, RuntimeError> {
1634 let _ = verify_state;
1635 let signature_from_anon = FnSet::new(
1636 anon.body.params_def_with_set.clone(),
1637 anon.body.dom_facts.clone(),
1638 (*anon.body.ret_set).clone(),
1639 )?;
1640 if signature_from_anon.to_string() == expected_fn_set.to_string() {
1641 return Ok(
1642 (FactualStmtSuccess::new_with_verified_by_builtin_rules_recording_stmt(
1643 in_fact.clone().into(),
1644 "anonymous function: signature (params, dom, co-domain) matches `fn` set"
1645 .to_string(),
1646 Vec::new(),
1647 ))
1648 .into(),
1649 );
1650 }
1651 let flat_a =
1652 ParamGroupWithSet::collect_param_names(&signature_from_anon.body.params_def_with_set);
1653 let flat_e =
1654 ParamGroupWithSet::collect_param_names(&expected_fn_set.body.params_def_with_set);
1655 if flat_a.len() != flat_e.len() {
1656 return Ok((StmtUnknown::new()).into());
1657 }
1658 let shared_names = self.generate_random_unused_names(flat_a.len());
1659 let a_norm = self
1660 .fn_set_alpha_renamed_for_display_compare(&signature_from_anon.body, &shared_names)?;
1661 let e_norm =
1662 self.fn_set_alpha_renamed_for_display_compare(&expected_fn_set.body, &shared_names)?;
1663 if a_norm.to_string() == e_norm.to_string() {
1664 return Ok(
1665 (FactualStmtSuccess::new_with_verified_by_builtin_rules_recording_stmt(
1666 in_fact.clone().into(),
1667 "anonymous function: signature matches `fn` set (alpha-renamed parameters)"
1668 .to_string(),
1669 Vec::new(),
1670 ))
1671 .into(),
1672 );
1673 }
1674 Ok((StmtUnknown::new()).into())
1675 }
1676
1677 fn verify_in_fact_by_known_standard_subset_membership(
1678 &mut self,
1679 in_fact: &InFact,
1680 target_set_obj: &Obj,
1681 ) -> Result<StmtResult, RuntimeError> {
1682 let standard_subset_set_objs =
1683 match Self::standard_subset_set_objs_for_target_set(target_set_obj) {
1684 Some(standard_subset_set_objs) => standard_subset_set_objs,
1685 None => return Ok((StmtUnknown::new()).into()),
1686 };
1687 for standard_subset_set_obj in standard_subset_set_objs.iter() {
1688 let in_fact_into_standard_subset = InFact::new(
1689 in_fact.element.clone(),
1690 standard_subset_set_obj.clone(),
1691 in_fact.line_file.clone(),
1692 )
1693 .into();
1694 let verify_result = self.verify_non_equational_atomic_fact_with_known_atomic_facts(
1695 &in_fact_into_standard_subset,
1696 )?;
1697 if verify_result.is_true() {
1698 return Ok(
1699 (FactualStmtSuccess::new_with_verified_by_builtin_rules_recording_stmt(
1700 in_fact.clone().into(),
1701 format!(
1702 "{} in {} implies in {} (standard subset relation)",
1703 in_fact.element, standard_subset_set_obj, target_set_obj
1704 ),
1705 Vec::new(),
1706 ))
1707 .into(),
1708 );
1709 }
1710 }
1711 Ok((StmtUnknown::new()).into())
1712 }
1713
1714 fn verify_in_fact_by_left_is_tuple_right_is_cart(
1715 &mut self,
1716 in_fact: &InFact,
1717 tuple: &Tuple,
1718 cart: &Cart,
1719 verify_state: &VerifyState,
1720 ) -> Result<StmtResult, RuntimeError> {
1721 if tuple.args.len() < 2 {
1722 return Ok((StmtUnknown::new()).into());
1723 }
1724 if tuple.args.len() != cart.args.len() {
1725 return Ok((StmtUnknown::new()).into());
1726 }
1727
1728 for component_index in 0..tuple.args.len() {
1729 let tuple_component_obj = (*tuple.args[component_index]).clone();
1730 let cart_component_obj = (*cart.args[component_index]).clone();
1731 let component_in_fact = InFact::new(
1732 tuple_component_obj,
1733 cart_component_obj,
1734 in_fact.line_file.clone(),
1735 )
1736 .into();
1737 let component_verify_result =
1738 self.verify_atomic_fact(&component_in_fact, verify_state)?;
1739 if !component_verify_result.is_true() {
1740 return Ok((StmtUnknown::new()).into());
1741 }
1742 }
1743
1744 Ok(
1745 (FactualStmtSuccess::new_with_verified_by_builtin_rules_recording_stmt(
1746 in_fact.clone().into(),
1747 "tuple in cart: each component is in the corresponding cart factor".to_string(),
1748 Vec::new(),
1749 ))
1750 .into(),
1751 )
1752 }
1753}