30 const std::shared_ptr<SymbolicExpr>& factor_expr,
34 (
context).limits().max_ast_nodes,
"transform");
39 if (mappings.empty()) {
43 auto result = factor_expr;
45 for (
const auto& m : mappings) {
46 if (!m.trans_expr || m.indeterminate.empty()) {
63 std::vector<std::shared_ptr<SymbolicExpr>>
run(
64 const std::vector<std::shared_ptr<SymbolicExpr>>& factors,
66 for (
const auto& factor : factors) {
86 bool append(
const std::shared_ptr<SymbolicExpr>& factor) {
88 if (
auto number = std::dynamic_pointer_cast<const NumberNode>(node)) {
91 if (
auto product = std::dynamic_pointer_cast<const MultiplyNode>(node)) {
101 if (
value == Rational(0)) {
103 result_.push_back(SymbolicExpr::number(0));
111 const std::vector<std::shared_ptr<const SymbolicNode>>& numeric,
112 std::vector<std::shared_ptr<const SymbolicNode>>& symbolic) {
113 for (
const auto& operand : numeric) {
114 auto number = std::dynamic_pointer_cast<const NumberNode>(operand);
117 if (symbolic.size() == 1) {
126 const std::vector<std::shared_ptr<const SymbolicNode>>& numeric) {
128 for (
const auto& operand : numeric) {
129 auto number = std::dynamic_pointer_cast<const NumberNode>(operand);
136 const std::shared_ptr<SymbolicExpr>& factor) {
137 std::vector<std::shared_ptr<const SymbolicNode>> numeric;
138 std::vector<std::shared_ptr<const SymbolicNode>> symbolic;
139 for (
const auto& operand : product.
operands()) {
140 if (std::dynamic_pointer_cast<const NumberNode>(operand)) {
141 numeric.push_back(operand);
143 symbolic.push_back(operand);
146 if (!numeric.empty() && !symbolic.empty()) {
148 }
else if (numeric.empty()) {
155 std::vector<std::shared_ptr<SymbolicExpr>>
result_;
168 std::vector<std::shared_ptr<SymbolicExpr>>& factors) {
176 context.limits().max_ast_nodes,
"factor_transcendental");
177 FactorSimplification simplification;
178 return simplification.run(factors, budget);
196 const std::string& var) {
208 for (
const auto& m : sub_result.
mappings) {
210 if (deg < 0 || deg > 1) {
218 if (deg < 0 || deg > 1) {
237 const std::shared_ptr<SymbolicExpr>& expr) {
244 if (!
mul ||
mul->operands().size() < 2) {
248 std::vector<std::shared_ptr<SymbolicExpr>> factors;
249 Rational constant_acc(1);
251 for (
const auto&
op :
mul->operands()) {
257 if (
op->is_number()) {
258 auto num = std::dynamic_pointer_cast<const NumberNode>(
op);
260 if (std::holds_alternative<BigInt>(
num->value())) {
261 constant_acc = constant_acc * Rational(std::get<BigInt>(
num->value()));
262 }
else if (std::holds_alternative<Rational>(
num->value())) {
263 constant_acc = constant_acc * std::get<Rational>(
num->value());
277 if (factors.size() < 2 && (factors.empty() || constant_acc == Rational(1))) {
282 if (constant_acc != Rational(1)) {
283 auto const_expr = SymbolicExpr::number(constant_acc);
284 factors.insert(factors.begin(), const_expr);
291 const std::shared_ptr<const SymbolicNode>& node,
const std::string& var) {
292 auto function = std::dynamic_pointer_cast<const FunctionNode>(node);
297 function->arguments().size() != 1) {
316 const std::shared_ptr<const SymbolicNode>& node,
317 const std::string& var) {
329 if (
auto mul = std::dynamic_pointer_cast<const MultiplyNode>(node)) {
330 for (
const auto&
op :
mul->operands()) {
352 const std::shared_ptr<const SymbolicNode>& node,
353 const std::shared_ptr<const SymbolicNode>& exp_factor) {
355 if (!node || !exp_factor) {
360 if (node->
equals(*exp_factor)) {
365 if (
auto mul = std::dynamic_pointer_cast<const MultiplyNode>(node)) {
366 std::vector<std::shared_ptr<const SymbolicNode>> remaining_ops;
367 bool removed =
false;
369 for (
const auto&
op :
mul->operands()) {
370 if (!removed &&
op->equals(*exp_factor)) {
374 remaining_ops.push_back(
op);
381 if (remaining_ops.empty()) {
384 if (remaining_ops.size() == 1) {
385 return remaining_ops[0];
410 const std::shared_ptr<SymbolicExpr>& expr,
414 (
context).limits().max_ast_nodes,
"transform");
421 if (!
add ||
add->operands().size() < 2) {
432 for (
size_t i = 1; i <
add->operands().size(); ++i) {
434 if (!term_exp || !term_exp->equals(*common_exp)) {
441 std::vector<std::shared_ptr<const SymbolicNode>> remainder_terms;
442 remainder_terms.reserve(
add->operands().size());
444 for (
const auto&
op :
add->operands()) {
446 remainder_terms.push_back(remainder);
452 std::shared_ptr<SymbolicExpr> sum_expr;
453 if (remainder_terms.size() == 1) {
463 sum_expr = simplified_sum;
466 return {exp_factor_expr, sum_expr};
482 const std::vector<std::shared_ptr<const SymbolicNode>>& nodes,
483 const std::string& var) {
484 for (
const auto& node : nodes) {
493 const std::shared_ptr<const SymbolicNode>& node,
494 const std::string& var) {
500 if (
auto func = std::dynamic_pointer_cast<const FunctionNode>(node)) {
501 if (func->arguments().size() == 1 &&
509 if (
auto add = std::dynamic_pointer_cast<const AddNode>(node)) {
513 if (
auto mul = std::dynamic_pointer_cast<const MultiplyNode>(node)) {
516 if (
auto pow = std::dynamic_pointer_cast<const PowerNode>(node)) {
const std::vector< std::shared_ptr< const SymbolicNode > > & operands() const noexcept
bool equals(const SymbolicNode &other) const
判断两个节点是否结构相等.
std::vector< std::shared_ptr< SymbolicExpr > > run(const std::vector< std::shared_ptr< SymbolicExpr > > &factors, detail::RewriteBudget &budget)
bool append(const std::shared_ptr< SymbolicExpr > &factor)
void accumulate_numeric_product(const std::vector< std::shared_ptr< const SymbolicNode > > &numeric)
void append_mixed_product(const std::vector< std::shared_ptr< const SymbolicNode > > &numeric, std::vector< std::shared_ptr< const SymbolicNode > > &symbolic)
std::vector< std::shared_ptr< SymbolicExpr > > result_
void append_product(const MultiplyNode &product, const std::shared_ptr< SymbolicExpr > &factor)
bool append_number(const NumberNode &number)
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)
SymbolicNodePtr substitute_node(const SymbolicNodePtr &node, const std::string &variable, const SymbolicNodePtr &replacement, RewriteBudget &budget, const FactsQuery &facts, Domain domain)
std::shared_ptr< SymbolicExpr > num(int value)
ExprResult pow(const ExprPtr &base, const ExprPtr &exponent, ComputationContext &context)
const std::vector< Polynomial< BigInt > > const BigInt ComputationContext & context
bool tf_is_linear_irreducible(const TransSubstitutionResult &substitution, const std::string &variable)
判断换元后的表达式是否对所有不定元和原始变量均为线性.
ExprResult mul(const ExprPtr &lhs, const ExprPtr &rhs, ComputationContext &context)
std::shared_ptr< SymbolicExpr > tf_back_substitute(const std::shared_ptr< SymbolicExpr > &expression, const std::vector< TransSubstitution > &mappings, ComputationContext &context)
将因子表达式中的不定元变量替换回原始超越子表达式.
static bool tf_is_variable_exponential(const std::shared_ptr< const SymbolicNode > &node, const std::string &var)
bool expression_depends_on_variable(const detail::SymbolicNodePtr &expression, const std::string &variable, detail::RewriteBudget *budget)
std::vector< std::shared_ptr< SymbolicExpr > > tf_detect_multiplicative_structure(const std::shared_ptr< SymbolicExpr > &expression)
检测表达式是否已为独立子表达式的乘积形式.
std::vector< std::shared_ptr< SymbolicExpr > > tf_simplify_factors_impl(const std::vector< std::shared_ptr< SymbolicExpr > > &factors, ComputationContext &context)
bool tf_contains_transcendental(const std::shared_ptr< const SymbolicNode > &node, const std::string &variable)
ExprResult add(const ExprPtr &lhs, const ExprPtr &rhs, ComputationContext &context)
std::shared_ptr< SymbolicExpr > poly_expr
换元后的多项式表达式
static std::shared_ptr< const SymbolicNode > tf_extract_exp_factor(const std::shared_ptr< const SymbolicNode > &node, const std::string &var)
从乘积项中提取指数函数因子.
std::vector< std::shared_ptr< SymbolicExpr > > tf_simplify_factors(std::vector< std::shared_ptr< SymbolicExpr > > &factors)
化简逆换元后的因子,合并数值因子及乘积的数值前导系数。 保留非常数部分,将非 1 的常数积置于结果首位。
const ExprPtr RelationOp op
static std::shared_ptr< const SymbolicNode > tf_remove_exp_factor(const std::shared_ptr< const SymbolicNode > &node, const std::shared_ptr< const SymbolicNode > &exp_factor)
从乘积项中移除指定的指数函数因子,返回剩余部分.
int tf_degree_in(const std::shared_ptr< const SymbolicNode > &node, const std::string &variable)
static bool any_transcendental(const std::vector< std::shared_ptr< const SymbolicNode > > &nodes, const std::string &var)
判断表达式 AST 中是否包含依赖指定变量的超越函数.
bool tf_is_transcendental_type(FunctionNode::FuncType function_type)
判断函数类型是否支持超越函数换元。
std::vector< std::shared_ptr< SymbolicExpr > > tf_detect_exponential_separation(const std::shared_ptr< SymbolicExpr > &expression, const std::string &variable, ComputationContext &context)
检测加法表达式中的公共指数因子并执行分离.
const std::string const ExprPtr & value
std::vector< TransSubstitution > mappings
所有换元映射
Rational exact_number_as_rational(const NumberNode &node)
ExprResult function(const std::string &name, std::vector< ExprPtr > arguments)