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