47 const SymbolicExpr& lhs,
const SymbolicExpr&
rhs,
50 auto left = std::make_shared<SymbolicExpr>(lhs);
51 auto right = std::make_shared<SymbolicExpr>(
rhs);
52 if (
auto quantity = std::dynamic_pointer_cast<const QuantityNode>(
detail::node(lhs))) {
55 if (!stripped) {
return OperandsResult::failure(stripped.error()); }
56 left = stripped.value();
58 if (
auto quantity = std::dynamic_pointer_cast<const QuantityNode>(
detail::node(
rhs))) {
61 if (!stripped) {
return OperandsResult::failure(stripped.error()); }
62 right = stripped.value();
64 return OperandsResult::success({std::move(left), std::move(
right)});
100 *operands.value().first, budget);
102 *operands.value().second, budget);
107 auto negative = SymbolicExpr::multiply(SymbolicExpr::number(-1),
right);
109 auto difference = SymbolicExpr::add(left, negative);
112 "equivalence difference construction failed",
125 "equivalence proof is inconclusive",
130 const SymbolicExpr& lhs,
const SymbolicExpr&
rhs,
141 if (lhs_dimension.value() != rhs_dimension.value()) {
163 const auto maximum = std::numeric_limits<std::size_t>::max();
164 const auto factor =
options.budget.max_node_growth_factor;
165 const auto growth_nodes = input_nodes > maximum / factor
166 ? maximum : input_nodes * factor;
167 const auto max_nodes = std::min(
context.limits().max_ast_nodes, growth_nodes);
174 }
catch (
const std::length_error& error) {
177 }
catch (
const std::bad_alloc&) {
179 "equivalence check allocation failed",
181 }
catch (
const std::exception& error) {
193 return left->equals(*
right);
197 const SymbolicExpr&
rhs,
static Result failure(CasErrc code, std::string message, std::string operation={})
static Result success(T value)
std::size_t measure(const std::shared_ptr< const SymbolicNode > &node)
static std::size_t input_nodes(const std::shared_ptr< const SymbolicNode > &lhs, const std::shared_ptr< const SymbolicNode > &rhs, ComputationContext &context, std::size_t max_depth, const char *operation)
Result< bool > apply_profile(const SymbolicExpr &lhs, const SymbolicExpr &rhs, ComputationContext &context, const EqvOptions &options, detail::RewriteBudget &budget)
Result< bool > prove_operands(const SymbolicExpr &lhs, const SymbolicExpr &rhs, ComputationContext &context, const EqvOptions &options, detail::RewriteBudget &budget)
Result< std::pair< ExprPtr, ExprPtr > > prepare_operands(const SymbolicExpr &lhs, const SymbolicExpr &rhs, ComputationContext &context, detail::RewriteBudget &budget)
Result< bool > prove_checked_operands(const SymbolicExpr &lhs, const SymbolicExpr &rhs, ComputationContext &context, const EqvOptions &options, detail::RewriteBudget &budget)
Result< bool > equivalent_with_budget(const SymbolicExpr &lhs, const SymbolicExpr &rhs, ComputationContext &context, const EqvOptions &options, detail::RewriteBudget *budget)
SymbolicNodePtr expand_node(const SymbolicNodePtr &node, RewriteBudget &budget, const FactsQuery &facts, Domain domain)
std::shared_ptr<::LMCAS::SymbolicExpr > make_expression_ptr(SymbolicNodePtr root)
const SymbolicNodePtr & node(const ::LMCAS::SymbolicExpr &expression) noexcept
std::optional< Rational > exact_rational_value(const NumberNode &number)
SymbolicNodePtr normalize_node(const SymbolicNodePtr &node, RewriteBudget &budget, const FactsQuery &facts, Domain domain)
std::size_t std::size_t ComputationContext & context
Result< bool > equivalent_impl(const SymbolicExpr &lhs, const SymbolicExpr &rhs, ComputationContext &context, const EqvOptions &options)
ExprPtr normalize_equivalence(const ExprPtr &expression, detail::RewriteBudget &budget)
Result< std::optional< bool > > prove_rational_polynomial_equivalence(const ExprPtr &difference, ComputationContext &context, const EqvOptions &options, detail::RewriteBudget &budget)
ExprPtr rewrite_trig_basic_identity(const detail::SymbolicNodePtr &node, detail::RewriteBudget &budget)
Result< void > validate_eqv_options(const EqvOptions &options)
ExprPtr expand_equivalence(const ExprPtr &expression, detail::RewriteBudget &budget)
ExprPtr rewrite_exp_log_basic_identity(const detail::SymbolicNodePtr &node, const AssumptionContext *assumptions, detail::RewriteBudget &budget)
ExprPtr canonicalize_complex_product(const SymbolicExpr &expression, detail::RewriteBudget &budget)
Result< DimensionSignature > dimension_of(const SymbolicExpr &expression)
const std::vector< Polynomial< BigInt > > const BigInt ComputationContext & context
const std::string ComputationContext const SolveOptions & options
std::size_t normalization_check_arithmetic(detail::RewriteBudget *budget, std::size_t extra_nodes, const std::shared_ptr< const Nodes > &... children)
std::shared_ptr< SymbolicExpr > ExprPtr
const std::string const ExprPtr & value
bool structurally_equal(const SymbolicExpr &lhs, const SymbolicExpr &rhs)
QuantityResult strip_unit(const std::shared_ptr< SymbolicExpr > &expression, UnitStripMode mode, ComputationContext &context)
constexpr const char * kEquivalentOperation