21using Expressions = std::vector<std::shared_ptr<SymbolicExpr>>;
27 (
context).limits().max_ast_nodes,
"transform");
29 std::vector<std::shared_ptr<const SymbolicNode>> factors;
34 auto cleared =
to_ptr(equation);
35 if (factors.empty()) {
37 }
else if (
auto sum = std::dynamic_pointer_cast<const AddNode>(
detail::node(cleared))) {
38 std::vector<std::shared_ptr<const SymbolicNode>> terms;
39 terms.reserve(sum->operands().size());
40 for (
const auto& term : sum->operands()) {
51 for (
const auto& constraint : local_constraints) constraints.push_back(constraint);
59 (
context).limits().max_ast_nodes,
"transform");
60 auto result = expression;
61 for (
const auto& [
name,
value] : solution) {
63 if (!result)
return nullptr;
70 std::optional<detail::AssumptionFacts> adapter;
71 if (
context.assumptions()) adapter.emplace(*
context.assumptions());
74 filtered.reserve(candidates.size());
75 for (
auto& solution : candidates) {
80 "denominator substitution failed",
"solve_polynomial_system");
86 "candidate denominator is not proved nonzero",
"solve_polynomial_system");
88 if (valid) filtered.push_back(std::move(solution));
100 for (
const auto& root : solved.value()) solutions.push_back({{
variable, *root}});
105 const std::vector<std::string>& variables,
108 constexpr const char* operation =
"solve_polynomial_system";
109 for (
const auto& equation : equations) {
110 auto budget =
context.consume_steps(1, operation);
121 const SymbolicExpr& polynomial,
const std::vector<std::string>& variables,
123 std::shared_ptr<SymbolicExpr>& simplified)
try {
125 (
context).limits().max_ast_nodes,
"transform");
126 constexpr const char* operation =
"solve_polynomial_system";
127 auto budget =
context.consume_steps(1, operation);
139}
catch (
const std::bad_alloc&) {
141}
catch (
const std::length_error& error) {
143}
catch (
const std::exception& error) {
148 const std::vector<std::string>& variables,
150 constexpr const char* operation =
"solve_polynomial_system";
156 std::vector<FGLMPoly> leading;
157 basis.reserve(groebner.size());
158 leading.reserve(groebner.size());
159 for (
const auto& polynomial : groebner) {
160 std::shared_ptr<SymbolicExpr> simplified;
163 if (simplified->is_number() && !simplified->is_zero())
return Expressions{simplified};
164 if (converted.value().is_zero())
continue;
165 FGLMPoly term(variables.size());
166 term.add_term(converted.value().lead_monomial(), converted.value().lead_coeff());
167 leading.push_back(std::move(term));
168 basis.push_back(std::move(simplified));
172 "polynomial system has no certified finite solution set", operation);
179 const std::vector<std::string>& variables,
199 for (
int index = 0; index <= last && index < static_cast<int>(
variables_.size()); ++index) {
208 reduced.reserve(
basis_.size());
209 for (
const auto& polynomial :
basis_) {
213 if (substituted->is_zero()) {
continue; }
217 if (std::holds_alternative<ProvedZeroResidual>(proof.value())) {
continue; }
218 std::optional<detail::AssumptionFacts> adapter;
223 if (nonzero.value() ==
Tribool::True) {
return std::optional<Expressions>{}; }
225 "remaining system constraint is not proved",
"solve_polynomial_system");
227 reduced.push_back(substituted);
229 return std::optional<Expressions>{std::move(reduced)};
234 std::shared_ptr<SymbolicExpr>
target;
235 int best_degree = std::numeric_limits<int>::max();
237 for (
const auto& polynomial : reduced) {
241 auto univariate = symbolic_to_poly<SymbolicPolyCoeff>(polynomial,
name);
248 int degree = univariate.value().degree();
249 if (degree >= 1 && degree < best_degree) {
250 best_degree = degree;
264 bool appears =
false;
269 "remaining variable is not constrained",
"solve_polynomial_system");
273 "No convertible polynomial target for remaining variable",
"solve_polynomial_system");
278 for (
const auto& root : solved.value()) {
280 next.insert_or_assign(
name, *root);
282 if (!solved_branch)
return solved_branch;
283 auto& values = solved_branch.value();
284 results.insert(results.end(), std::make_move_iterator(values.begin()),
285 std::make_move_iterator(values.end()));
291 const std::vector<SymbolicExpr>& equations,
293 std::vector<SymbolicExpr> cleared_equations;
295 cleared_equations.reserve(equations.size());
296 for (
const auto& equation : equations) {
299 "equation cannot be converted to a polynomial without losing its domain",
"solve_polynomial_system");
300 cleared_equations.push_back(*cleared);
302 if (cleared_equations.size() == 1 && variables.size() == 1) {
304 if (!solved)
return solved;
309 if (
basis.value().size() == 1 &&
basis.value().front()->is_number() &&
313 if (!solved)
return solved;
319 const std::vector<SymbolicExpr>& equations,
320 const std::vector<std::string>& variables, ComputationContext&
context) {
321 constexpr const char* operation =
"solve_polynomial_system";
322 if (equations.empty() || variables.empty()) {
325 "polynomial system requires equations and variables", operation);
327 auto budget =
context.consume_steps(equations.size() * variables.size() + 1, operation);
333 }
catch (
const std::bad_alloc&) {
336 "allocation failed while solving polynomial system", operation);
337 }
catch (
const std::length_error& error) {
339 }
catch (
const std::exception& error) {
345 const std::vector<SymbolicExpr>& equations,
346 const std::vector<std::string>& variables) {
348 return solve_polynomial_system_checked(equations, variables,
context);
static Result failure(CasErrc code, std::string message, std::string operation={})
static Result success(T value)
virtual void accept(LMCAS::detail::SymbolicVisitor &visitor) const =0
PolynomialSystemResult solve(int variable, const PolynomialSolution &partial) const
PolynomialSystemSearch(const Expressions &basis, const std::vector< std::string > &variables, ComputationContext &context)
bool depends_on_remaining(const SymbolicExpr &expression, int last) const
const std::vector< std::string > & variables_
Result< std::shared_ptr< SymbolicExpr > > select_equation(const Expressions &reduced, int variable, bool &appears) const
Result< std::optional< Expressions > > substitute_basis(int variable, const PolynomialSolution &partial) const
const Expressions & basis_
ComputationContext & context_
FGLM 算法:零维理想 Gröbner 基在不同单项式序之间的转换.
PolynomialSystemResult solve_polynomial_system_impl(const std::vector< SymbolicExpr > &equations, const std::vector< std::string > &variables, ComputationContext &context)
std::vector< std::shared_ptr< SymbolicExpr > > Expressions
std::vector< PolynomialSolution > PolynomialSolutions
std::map< std::string, SymbolicExpr > PolynomialSolution
PolynomialSystemResult filter_denominators(PolynomialSolutions candidates, const Expressions &constraints, ComputationContext &context)
Result< Expressions > simplified_basis(const std::vector< SymbolicExpr > &equations, const std::vector< std::string > &variables, ComputationContext &context)
Result< groebner_detail::Poly > convert_basis_polynomial(const SymbolicExpr &polynomial, const std::vector< std::string > &variables, groebner_detail::PolyContext &conversion, ComputationContext &context, std::shared_ptr< SymbolicExpr > &simplified)
std::shared_ptr< SymbolicExpr > clear_denominators(const SymbolicExpr &equation, Expressions &constraints, ComputationContext &context)
Result< void > validate_basis_input(const std::vector< SymbolicExpr > &equations, const std::vector< std::string > &variables, groebner_detail::PolyContext &conversion, ComputationContext &context)
PolynomialSystemResult solve_single_equation(const SymbolicExpr &equation, const std::string &variable, ComputationContext &context)
std::shared_ptr< SymbolicExpr > substitute_solution(const std::shared_ptr< SymbolicExpr > &expression, const PolynomialSolution &solution, ComputationContext &context)
std::shared_ptr<::LMCAS::SymbolicExpr > make_expression_ptr(SymbolicNodePtr root)
const SymbolicNodePtr & node(const ::LMCAS::SymbolicExpr &expression) noexcept
Result< Tribool > query_nonzero_value(const Node &node, const FactsQuery &facts, Domain domain, ComputationContext &context)
const FactsQuery & no_facts() 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::vector< SymbolicExpr > reduced_groebner_basis_impl(const std::vector< SymbolicExpr > &polynomials, const std::vector< std::string > &variables, ComputationContext &context)
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)
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)
const std::string & variable
const std::vector< Polynomial< BigInt > > const BigInt ComputationContext & context
@ Complex
Complex numbers (default, least specific)
@ True
Property definitely holds
@ False
Property definitely does not hold
bool is_zero_dimensional(const std::vector< FGLMPoly > &basis, size_t num_vars)
bool contains(const SymbolicExpr &expression, const std::string &variable)
Result< std::vector< std::map< std::string, SymbolicExpr > > > PolynomialSystemResult
多项式方程组求解器,提供线性系统求解、Gröbner 基计算及多项式系统求解功能。
LMCAS::FiniteSolveResult solve_finite_checked(const std::shared_ptr< SymbolicExpr > &expr, const std::string &var, ComputationContext &context, const SolveOptions &opts)
const std::vector< FGLMPoly > & basis
ResidualCheckResult check_zero_residual(const ExprPtr &residual, ComputationContext &context, const LMCAS::EqvOptions &options)
const std::string const ExprPtr & value
const ExprPtr & denominator
__attribute__((visibility("default"))) Result< EqvProfile > eqv_profile_from_name(const std const std::string & name
ExprSetResult solve(const ExprPtr &equation, const std::string &variable, ComputationContext &context, const SolveOptions &options)
方程求解策略调度器 solve_dispatch 及相关选项结构体.
多项式方程组求解器 Solver,包含 Gröbner 基、线性系统求解。