17 if (std::holds_alternative<BigInt>(
value)) {
19 if (!
integer.is_negative()) {
return nullptr; }
23 if (!
rational.get_numerator().is_negative()) {
return nullptr; }
29 std::vector<CancellationNode>& numerator, std::vector<CancellationNode>&
denominator) {
30 auto power = std::dynamic_pointer_cast<const PowerNode>(factor);
32 auto exponent = std::dynamic_pointer_cast<const NumberNode>(power->exponent());
35 auto number = std::dynamic_pointer_cast<const NumberNode>(positive);
36 if (number && number->is_one()) {
44 numerator.push_back(factor);
48 std::vector<CancellationNode>& numerator, std::vector<CancellationNode>&
denominator) {
49 if (
auto product = std::dynamic_pointer_cast<const MultiplyNode>(node)) {
50 for (
const auto& operand : product->operands()) {
59 if (factors.empty()) {
return SymbolicExpr::number(1); }
73 (
context).limits().max_ast_nodes,
"transform");
74 bool has_denominator =
false;
75 for (
const auto& term : addition.
operands()) {
76 std::vector<CancellationNode> numerator,
denominator;
80 if (!den_expr->is_one()) { has_denominator =
true; }
81 terms.push_back({num_expr, den_expr});
83 return has_denominator;
87 auto first = terms[0].denominator->to_string();
88 for (
size_t i = 1; i < terms.size(); ++i) {
89 if (terms[i].
denominator->to_string() != first) {
return false; }
98 (
context).limits().max_ast_nodes,
"transform");
99 auto total_den = SymbolicExpr::number(1);
100 std::vector<CancellationExpr> unique_dens;
101 for (
const auto& term : terms) {
102 if (term.denominator->is_one()) {
continue; }
105 if (
denominator->to_string() == term.denominator->to_string()) {
110 if (!found) { unique_dens.push_back(term.denominator); }
122 (
context).limits().max_ast_nodes,
"transform");
125 std::vector<CancellationNode> operands;
126 for (
const auto& term : terms) {
127 auto numerator = term.numerator;
131 auto factor = total_node && term_node &&
132 total_node->
compare(*term_node) == 0
133 ? SymbolicExpr::number(1)
135 denominator, term.denominator)), transform_budget));
137 term.numerator, factor)), transform_budget));
143 if (operands.empty()) {
return {SymbolicExpr::number(0),
nullptr}; }
151template <
typename Coefficient>
157 (
context).limits().max_ast_nodes,
"transform");
160 if (gcd.degree() >= 1) {
161 auto [q_num, r_num] = numerator.
div_mod(gcd);
163 if (!r_num.is_zero() || !r_den.is_zero())
return;
173 (
context).limits().max_ast_nodes,
"transform");
176 auto rational_num = symbolic_to_poly<Rational>(num_expanded, var);
177 auto rational_den = symbolic_to_poly<Rational>(den_expanded, var);
178 if (rational_num && rational_den) {
179 if (rational_den.value().is_zero()) {
return simp; }
180 if (rational_num.value().is_zero()) {
return SymbolicExpr::number(0); }
184 auto symbolic_num = symbolic_to_poly<SymbolicPolyCoeff>(num_expanded, var);
185 auto symbolic_den = symbolic_to_poly<SymbolicPolyCoeff>(den_expanded, var);
186 if (!symbolic_num || !symbolic_den) {
return nullptr; }
187 if (symbolic_den.value().is_zero()) {
return simp; }
188 if (symbolic_num.value().is_zero()) {
return SymbolicExpr::number(0); }
197 (
context).limits().max_ast_nodes,
"transform");
198 if (cur_den->is_one()) {
return cur_num; }
201 SymbolicExpr::number(-1))), transform_budget));
202 if (diff->is_zero()) {
213 (
context).limits().max_ast_nodes,
"transform");
216 rational_variables.insert(denominator_variables.begin(), denominator_variables.end());
217 if (!from_sum && rational_variables.empty()) {
220 for (
const auto& var : rational_variables) {
224 if (terminal) {
return terminal; }
225 }
catch (
const std::invalid_argument&) {
227 }
catch (
const std::out_of_range&) {
229 }
catch (
const std::runtime_error&) {
238std::shared_ptr<SymbolicExpr> SymbolicExpr::cancel()
const {
240 detail::RewriteBudget transform_budget(
context, (
context).limits().max_recursion_depth,
241 (
context).limits().max_ast_nodes,
"transform");
244 if (
auto addition = std::dynamic_pointer_cast<const AddNode>(
detail::node(simp))) {
245 std::vector<CancellationFraction> terms;
246 if (collect_fraction_terms(*addition, terms,
context)) {
247 auto combined = combine_fraction_terms(terms,
context);
248 if (!combined.denominator) {
return combined.numerator; }
253 std::vector<CancellationNode> num_factors;
254 std::vector<CancellationNode> den_factors;
256 if (den_factors.empty()) {
return simp; }
const std::vector< std::shared_ptr< const SymbolicNode > > & operands() const noexcept
static Polynomial gcd(Polynomial a, Polynomial b)
计算两个多项式的最大公因式
std::pair< Polynomial, Polynomial > div_mod(const Polynomial &other) const
多项式带余除法
int compare(const SymbolicNode &other) const
与另一个节点进行全序比较.
std::shared_ptr< const SymbolicNode > CancellationNode
static CancellationFraction combine_fraction_terms(const std::vector< CancellationFraction > &terms, ComputationContext &context)
static CancellationExpr reduce_fraction(CancellationFraction fraction, const CancellationExpr &simp, bool from_sum, ComputationContext &context)
static bool collect_fraction_terms(const AddNode &addition, std::vector< CancellationFraction > &terms, ComputationContext &context)
CancellationExpr denominator
static bool same_denominators(const std::vector< CancellationFraction > &terms)
static CancellationExpr distinct_denominator_product(const std::vector< CancellationFraction > &terms, ComputationContext &context)
static CancellationNode positive_denominator_exponent(const NumberNode &exponent)
static CancellationExpr cancel_variable(CancellationExpr &cur_num, CancellationExpr &cur_den, const std::string &var, const CancellationExpr &simp, ComputationContext &context)
static void cancel_polynomial_gcd(const Polynomial< Coefficient > &numerator, const Polynomial< Coefficient > &denominator, CancellationExpr &cur_num, CancellationExpr &cur_den, ComputationContext &context)
static CancellationExpr build_product(const std::vector< CancellationNode > &factors)
static void separate_num_den(const CancellationNode &node, std::vector< CancellationNode > &numerator, std::vector< CancellationNode > &denominator)
static CancellationExpr finish_cancellation(const CancellationExpr &cur_num, const CancellationExpr &cur_den, ComputationContext &context)
static void classify_fraction_factor(const CancellationNode &factor, std::vector< CancellationNode > &numerator, std::vector< CancellationNode > &denominator)
std::shared_ptr< SymbolicExpr > CancellationExpr
CancellationExpr numerator
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::shared_ptr< const Node > make_node(Args &&... args)
SymbolicNodePtr normalize_node(const SymbolicNodePtr &node, RewriteBudget &budget, const FactsQuery &facts, Domain domain)
const std::vector< Polynomial< BigInt > > const BigInt ComputationContext & context
ExprResult integer(Integer)=delete
std::set< std::string > free_variables(const detail::SymbolicNodePtr &expression, detail::RewriteBudget *budget)
const std::string const ExprPtr & value
const ExprPtr & denominator
ExprResult rational(const Rational &value)
符号表达式主类 SymbolicExpr 及其工厂方法,运算接口.