Branch data Line data Source code
1 : : /****************************************************************************** 2 : : * This file is part of the cvc5 project. 3 : : * 4 : : * Copyright (c) 2009-2026 by the authors listed in the file AUTHORS 5 : : * in the top-level source directory and their institutional affiliations. 6 : : * All rights reserved. See the file COPYING in the top-level source 7 : : * directory for licensing information. 8 : : * **************************************************************************** 9 : : * 10 : : * Represents a contraction candidate for ICP-style propagation. 11 : : */ 12 : : 13 : : #include "theory/arith/nl/icp/candidate.h" 14 : : 15 : : #ifdef CVC5_POLY_IMP 16 : : 17 : : #include <iostream> 18 : : 19 : : #include "base/check.h" 20 : : #include "base/output.h" 21 : : #include "theory/arith/nl/icp/intersection.h" 22 : : #include "theory/arith/nl/poly_conversion.h" 23 : : 24 : : namespace cvc5::internal { 25 : : namespace theory { 26 : : namespace arith { 27 : : namespace nl { 28 : : namespace icp { 29 : : 30 : 16 : PropagationResult Candidate::propagate(poly::IntervalAssignment& ia, 31 : : std::size_t size_threshold) const 32 : : { 33 : : // Evaluate the right hand side 34 : 32 : auto res = poly::evaluate(rhs, ia) * poly::Interval(poly::Value(rhsmult)); 35 [ + + ][ - - ]: 32 : if (get_lower(res) == poly::Value::minus_infty() 36 [ + + ][ + + ]: 32 : && get_upper(res) == poly::Value::plus_infty()) [ + + ][ + - ] [ - - ] 37 : : { 38 : 12 : return PropagationResult::NOT_CHANGED; 39 : : } 40 [ + - ]: 4 : Trace("nl-icp") << "Prop: " << *this << " -> " << res << std::endl; 41 : : // Remove bounds based on the sign condition 42 [ + - ][ - - ]: 4 : switch (rel) [ - - ][ - ] 43 : : { 44 : 4 : case poly::SignCondition::LT: 45 : 4 : res.set_lower(poly::Value::minus_infty(), true); 46 : 4 : res.set_upper(get_upper(res), true); 47 : 4 : break; 48 : 0 : case poly::SignCondition::LE: 49 : 0 : res.set_lower(poly::Value::minus_infty(), true); 50 : 0 : break; 51 : 0 : case poly::SignCondition::EQ: break; 52 : 0 : case poly::SignCondition::NE: DebugUnhandled(); break; 53 : 0 : case poly::SignCondition::GT: 54 : 0 : res.set_lower(get_lower(res), true); 55 : 0 : res.set_upper(poly::Value::plus_infty(), true); 56 : 0 : break; 57 : 0 : case poly::SignCondition::GE: 58 : 0 : res.set_upper(poly::Value::plus_infty(), true); 59 : 0 : break; 60 : : } 61 : : // Get the current interval for lhs 62 : 4 : auto cur = ia.get(lhs); 63 : : 64 : : // Update the current interval 65 : 4 : PropagationResult result = intersect_interval_with(cur, res, size_threshold); 66 : : // Check for strong propagations 67 [ - - ][ + ]: 4 : switch (result) 68 : : { 69 : 0 : case PropagationResult::CONTRACTED: 70 : : case PropagationResult::CONTRACTED_WITHOUT_CURRENT: 71 : : { 72 [ - - ]: 0 : Trace("nl-icp") << *this << " contracted " 73 : 0 : << stream_variable(polyCtx, lhs) << " -> " << cur 74 : 0 : << std::endl; 75 : 0 : auto old = ia.get(lhs); 76 : 0 : bool strong = false; 77 : 0 : strong = strong 78 : 0 : || (is_minus_infinity(get_lower(old)) 79 [ - - ]: 0 : && !is_minus_infinity(get_lower(cur))); 80 : 0 : strong = strong 81 : 0 : || (is_plus_infinity(get_upper(old)) 82 [ - - ]: 0 : && !is_plus_infinity(get_upper(cur))); 83 : 0 : ia.set(lhs, cur); 84 [ - - ]: 0 : if (strong) 85 : : { 86 [ - - ]: 0 : if (result == PropagationResult::CONTRACTED) 87 : : { 88 : 0 : result = PropagationResult::CONTRACTED_STRONGLY; 89 : : } 90 [ - - ]: 0 : else if (result == PropagationResult::CONTRACTED_WITHOUT_CURRENT) 91 : : { 92 : 0 : result = PropagationResult::CONTRACTED_STRONGLY_WITHOUT_CURRENT; 93 : : } 94 : : } 95 : 0 : break; 96 : 0 : } 97 : 0 : case PropagationResult::CONTRACTED_STRONGLY: 98 : : case PropagationResult::CONTRACTED_STRONGLY_WITHOUT_CURRENT: 99 : 0 : DebugUnhandled() << "This method should not return strong flags."; 100 : : break; 101 : 4 : default: break; 102 : : } 103 : 4 : return result; 104 : 16 : } 105 : : 106 : 0 : std::ostream& operator<<(std::ostream& os, const Candidate& c) 107 : : { 108 : 0 : os << stream_variable(c.polyCtx, c.lhs) << " " << c.rel << " "; 109 [ - - ]: 0 : if (c.rhsmult != poly::Rational(1)) os << c.rhsmult << " * "; 110 : 0 : return os << c.rhs; 111 : : } 112 : : 113 : : } // namespace icp 114 : : } // namespace nl 115 : : } // namespace arith 116 : : } // namespace theory 117 : : } // namespace cvc5::internal 118 : : 119 : : #endif