17#include <unordered_map>
31 auto num = std::dynamic_pointer_cast<const NumberNode>(node);
35 if (std::holds_alternative<BigInt>(
num->value())) {
36 value = std::get<BigInt>(
num->value());
39 if (std::holds_alternative<Rational>(
num->value())) {
40 const auto&
r = std::get<Rational>(
num->value());
41 if (!
r.is_integer()) {
50static std::shared_ptr<const NumberNode>
add_number_nodes(
const std::shared_ptr<const NumberNode>&
a,
const std::shared_ptr<const NumberNode>&
b) {
51 if (std::holds_alternative<Rational>(
a->
value()) || std::holds_alternative<Rational>(
b->value())) {
52 Rational r1 = std::holds_alternative<Rational>(
a->
value()) ? std::get<Rational>(
a->
value()) : Rational(std::get<BigInt>(
a->
value()));
53 Rational r2 = std::holds_alternative<Rational>(
b->value()) ? std::get<Rational>(
b->value()) : Rational(std::get<BigInt>(
b->value()));
60static std::shared_ptr<const NumberNode>
multiply_number_nodes(
const std::shared_ptr<const NumberNode>&
a,
const std::shared_ptr<const NumberNode>&
b) {
61 if (std::holds_alternative<Rational>(
a->
value()) || std::holds_alternative<Rational>(
b->value())) {
62 Rational r1 = std::holds_alternative<Rational>(
a->
value()) ? std::get<Rational>(
a->
value()) : Rational(std::get<BigInt>(
a->
value()));
63 Rational r2 = std::holds_alternative<Rational>(
b->value()) ? std::get<Rational>(
b->value()) : Rational(std::get<BigInt>(
b->value()));
71 bool operator()(
const std::shared_ptr<const SymbolicNode>&
a,
const std::shared_ptr<const SymbolicNode>&
b)
const {
75 return a->compare(*
b) < 0;
80 const std::shared_ptr<const SymbolicNode>& term,
81 const std::vector<std::shared_ptr<const SymbolicNode>>& den_factors
83 std::vector<std::shared_ptr<const SymbolicNode>> factors;
84 if (
auto mul = std::dynamic_pointer_cast<const MultiplyNode>(term)) {
85 factors.insert(factors.end(),
mul->operands().begin(),
mul->operands().end());
87 factors.push_back(term);
89 factors.insert(factors.end(), den_factors.begin(), den_factors.end());
91 std::shared_ptr<const NumberNode> const_acc =
93 std::map<std::shared_ptr<const SymbolicNode>, std::shared_ptr<const NumberNode>,
NodeLess> bases;
95 for (
const auto&
op : factors) {
99 if (
auto num = std::dynamic_pointer_cast<const NumberNode>(
op)) {
104 std::shared_ptr<const SymbolicNode> base =
op;
106 if (
auto pow = std::dynamic_pointer_cast<const PowerNode>(
op)) {
108 if (
auto e_num = std::dynamic_pointer_cast<const NumberNode>(
pow->exponent())) {
113 auto it = bases.find(base);
114 if (it == bases.end()) {
121 std::vector<std::shared_ptr<const SymbolicNode>> final_ops;
122 if (!const_acc->is_one()) final_ops.push_back(const_acc);
124 for (
const auto& [base,
exp] : bases) {
125 if (
exp->is_zero()) {
128 if (
exp->is_one()) final_ops.push_back(base);
132 if (final_ops.empty()) {
133 return SymbolicExpr::number(1);
135 if (final_ops.size() == 1) {
145 if (std::dynamic_pointer_cast<const NumberNode>(node)) {
148 if (std::dynamic_pointer_cast<const VariableNode>(node)) {
152 if (
auto add = std::dynamic_pointer_cast<const AddNode>(node)) {
153 for (
const auto&
op :
add->operands()) {
161 if (
auto mul = std::dynamic_pointer_cast<const MultiplyNode>(node)) {
162 for (
const auto&
op :
mul->operands()) {
170 if (
auto pow = std::dynamic_pointer_cast<const PowerNode>(node)) {
185 const std::vector<std::shared_ptr<const SymbolicNode>>& operands,
186 std::vector<std::shared_ptr<const SymbolicNode>>& den_factors,
187 std::vector<std::shared_ptr<SymbolicExpr>>& den_constraints) {
188 for (
const auto& operand : operands) {
198 std::vector<std::shared_ptr<const SymbolicNode>>& den_factors,
199 std::vector<std::shared_ptr<SymbolicExpr>>& den_constraints) {
211 den_factors.push_back(power.
base());
226 const std::shared_ptr<const SymbolicNode>& node,
227 std::vector<std::shared_ptr<const SymbolicNode>>& den_factors,
228 std::vector<std::shared_ptr<SymbolicExpr>>& den_constraints
234 if (std::dynamic_pointer_cast<const NumberNode>(node) || std::dynamic_pointer_cast<const VariableNode>(node)) {
238 if (
auto add = std::dynamic_pointer_cast<const AddNode>(node)) {
242 if (
auto mul = std::dynamic_pointer_cast<const MultiplyNode>(node)) {
246 if (
auto pow = std::dynamic_pointer_cast<const PowerNode>(node)) {
250 if (
auto func = std::dynamic_pointer_cast<const FunctionNode>(node)) {
260 (
context).limits().max_ast_nodes,
"transform");
262 auto expr_ptr =
to_ptr(expr);
265 std::vector<std::shared_ptr<const SymbolicNode>> mops;
270 std::vector<std::shared_ptr<const SymbolicNode>> nops;
272 nops.push_back(term_Ax);
275 std::vector<std::shared_ptr<const SymbolicNode>> aops;
277 aops.push_back(neg_term);
290std::map<std::string, SymbolicExpr> Solver::solve_linear_system(
291 const std::vector<SymbolicExpr>& equations_in,
292 const std::vector<std::string>& variables)
299 const std::vector<SymbolicExpr>& equations,
314 const std::vector<SymbolicExpr>& equations_in,
317 context.limits().max_ast_nodes,
"solve_linear_system");
319 size_t num_vars = variables.size();
320 size_t num_eqs = equations_in.size();
322 std::vector<std::vector<std::shared_ptr<SymbolicExpr>>> matrix(num_eqs, std::vector<std::shared_ptr<SymbolicExpr>>(num_vars + 1));
324 for (
size_t i = 0; i < num_eqs; ++i) {
325 SymbolicExpr current_eq = equations_in[i];
327 SymbolicExpr constant_part = current_eq;
329 for (
size_t j = 0; j < num_vars; ++j) {
333 constant_part = remainder;
336 std::vector<std::shared_ptr<const SymbolicNode>> ops;
344 num_eqs, num_vars + 1, {}};
345 augmented.
entries.reserve(num_eqs * (num_vars + 1));
346 for (
const auto& row : matrix) {
348 augmented.
entries.end(), row.begin(), row.end());
352 std::move(augmented), num_vars,
context,
353 "solve_linear_system");
354 if (!solved)
throw solved.error();
355 if (std::holds_alternative<detail::InconsistentLinearSolution>(solved.value())) {
359 std::vector<std::shared_ptr<SymbolicExpr>> values;
361 std::get_if<detail::UniqueLinearSolution>(&solved.value())) {
362 values = std::move(unique->values);
365 std::get<detail::ParametricLinearSolution>(solved.value());
366 values = parametric.particular;
367 for (std::size_t parameter = 0;
368 parameter < parametric.free_columns.size(); ++parameter) {
369 auto free_variable = SymbolicExpr::variable(
370 variables[parametric.free_columns[parameter]]);
371 for (std::size_t column = 0; column < num_vars; ++column) {
372 auto term = SymbolicExpr::multiply(
373 parametric.nullspace_basis[parameter][column],
376 values[column], term)), transform_budget));
381 std::map<std::string, SymbolicExpr> solution;
382 for (std::size_t column = 0; column < num_vars; ++column) {
383 solution.insert_or_assign(
384 variables[column], *values[column]);
AssumptionContext class with scoped push/pop management.
const std::shared_ptr< const SymbolicNode > & exponent() const noexcept
const std::shared_ptr< const SymbolicNode > & base() const noexcept
static std::shared_ptr< const SymbolicNode > create_add(std::vector< std::shared_ptr< const SymbolicNode > > ops, detail::RewriteBudget *budget=nullptr)
创建加法节点,自动扁平化嵌套加法并消除零项.
static std::shared_ptr< const SymbolicNode > create_variable(const std::string &name)
static std::shared_ptr< const SymbolicNode > create_power(std::shared_ptr< const SymbolicNode > base, std::shared_ptr< const SymbolicNode > exponent)
创建幂运算节点,自动处理指数为 0/1 及底数为 0/1 的情况.
static std::shared_ptr< const SymbolicNode > create_multiply(std::vector< std::shared_ptr< const SymbolicNode > > ops, detail::RewriteBudget *budget=nullptr)
创建乘法节点,自动扁平化嵌套乘法并消除单位元.
static std::shared_ptr< const SymbolicNode > create_number(const ::LMCAS::BigInt &v)
SymbolicNodePtr differentiate_node(const SymbolicNodePtr &node, const std::string &variable, 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
inline ::LMCAS::SymbolicExpr expression_from_node(SymbolicNodePtr root)
Result< ExactLinearSolution > solve_linear_exact(ExactMatrixData augmented, std::size_t coefficient_columns, ComputationContext &context, const std::string &operation)
std::shared_ptr< const Node > make_node(Args &&... args)
SymbolicNodePtr normalize_node(const SymbolicNodePtr &node, RewriteBudget &budget, const FactsQuery &facts, Domain domain)
std::shared_ptr< SymbolicExpr > num(int value)
bool is_polynomial_node(const std::shared_ptr< const SymbolicNode > &node)
std::shared_ptr< SymbolicExpr > multiply_no_expand(const std::shared_ptr< const SymbolicNode > &term, const std::vector< std::shared_ptr< const SymbolicNode > > &denominator_factors)
std::map< std::string, SymbolicExpr > solve_linear_system_impl(const std::vector< SymbolicExpr > &equations, const std::vector< std::string > &variables, ComputationContext &context)
std::map< std::string, SymbolicExpr > project_unconditional_linear_system(const std::vector< SymbolicExpr > &equations, const std::vector< std::string > &variables, ComputationContext &context)
bool collect_denominator_factors(const std::shared_ptr< const SymbolicNode > &node, std::vector< std::shared_ptr< const SymbolicNode > > &denominator_factors, std::vector< std::shared_ptr< SymbolicExpr > > &denominator_constraints)
std::shared_ptr< SymbolicExpr > to_ptr(const SymbolicExpr &expression)
ExprResult pow(const ExprPtr &base, const ExprPtr &exponent, ComputationContext &context)
ExprResult exp(const ExprPtr &expression, ComputationContext &context)
__attribute__((visibility("default"))) ComplexSymbolicResult complex_exp_form_checked(std __attribute__((visibility("default"))) ComplexSymbolicResult complex_exp_form_checked(std __attribute__((visibility("default"))) ComplexSymbolicResult complex_trig_form_checked(std __attribute__((visibility("default"))) ComplexSymbolicResult complex_trig_form_checked(std __attribute__((visibility("default"))) ComplexRootsResult solve_complex_nth_root_checked(std __attribute__((visibility("default"))) ComplexRootsResult solve_complex_nth_root_checked(std __attribute__((visibility("default"))) ComplexRootsResult solve_complex_quadratic_checked(std __attribute__((visibility("default"))) ComplexRootsResult solve_complex_quadratic_checked(std std::shared_ptr< SymbolicExpr > r
const std::vector< Polynomial< BigInt > > const BigInt ComputationContext & context
static std::shared_ptr< const NumberNode > multiply_number_nodes(const std::shared_ptr< const NumberNode > &a, const std::shared_ptr< const NumberNode > &b)
ExprResult mul(const ExprPtr &lhs, const ExprPtr &rhs, ComputationContext &context)
ExprResult add(const ExprPtr &lhs, const ExprPtr &rhs, ComputationContext &context)
const ExprPtr RelationOp op
__attribute__((visibility("default"))) VectorCalculusExprResult curve_integral_scalar_checked(const std __attribute__((visibility("default"))) VectorCalculusExprResult curve_integral_scalar_checked(const std __attribute__((visibility("default"))) std const VectorField const std::string const std::shared_ptr< SymbolicExpr > & a
static bool collect_power_denominators(const PowerNode &power, std::vector< std::shared_ptr< const SymbolicNode > > &den_factors, std::vector< std::shared_ptr< SymbolicExpr > > &den_constraints)
static std::pair< SymbolicExpr, SymbolicExpr > isolate_linear_coeff(const SymbolicExpr &expr, const std::string &var, ComputationContext &context)
const std::string const ExprPtr & value
static bool collect_operand_denominators(const std::vector< std::shared_ptr< const SymbolicNode > > &operands, std::vector< std::shared_ptr< const SymbolicNode > > &den_factors, std::vector< std::shared_ptr< SymbolicExpr > > &den_constraints)
static std::shared_ptr< const NumberNode > add_number_nodes(const std::shared_ptr< const NumberNode > &a, const std::shared_ptr< const NumberNode > &b)
static bool get_integer_value(const std::shared_ptr< const SymbolicNode > &node, BigInt &value)
多项式方程组求解器 Solver,包含 Gröbner 基、线性系统求解。
bool operator()(const std::shared_ptr< const SymbolicNode > &a, const std::shared_ptr< const SymbolicNode > &b) const
std::vector< ExprPtr > entries