13 const std::shared_ptr<SymbolicExpr>& expr,
18 (
context).limits().max_ast_nodes,
"transform");
24 const std::shared_ptr<SymbolicExpr>& expr,
29 (
context).limits().max_ast_nodes,
"transform");
33 for (
const auto& var : unknowns) {
39bool ParametricSolver::is_linear_in_unknowns(
40 const std::vector<std::shared_ptr<SymbolicExpr>>& equations,
41 const std::vector<std::string>& unknowns, ComputationContext&
context)
44 detail::RewriteBudget transform_budget(
context, (
context).limits().max_recursion_depth,
45 (
context).limits().max_ast_nodes,
"transform");
46 for (
const auto&
eq : equations) {
47 for (
const auto& var : unknowns) {
51 if (!second_deriv->is_zero()) {
55 for (
const auto& other_var : unknowns) {
56 if (other_var == var) {
60 if (!mixed->is_zero()) {
75 if (!residual)
throw residual.error();
76 if (std::holds_alternative<ProvedZeroResidual>(residual.value()))
return true;
78 "parameter coefficient or constraint is undecided",
"solve.parametric"};
83 std::optional<detail::AssumptionFacts> assumptions;
84 if (
context.assumptions()) assumptions.emplace(*
context.assumptions());
87 if (!nonzero)
throw nonzero.error();
88 return nonzero.value();
93 if (expression->is_zero())
return true;
103 (
context).limits().max_ast_nodes,
"transform");
104 while (row < matrix.size()) {
106 matrix[row][column] = simplified;
119 (
context).limits().max_ast_nodes,
"transform");
121 auto pivot = A[current_row][col];
123 for (
size_t r = 0;
r < m; ++
r) {
124 if (
r == current_row) {
128 if (entry->is_zero()) {
134 for (
size_t k = col; k < n; ++k) {
135 auto term = SymbolicExpr::multiply(factor, A[current_row][k]);
139 auto b_term = SymbolicExpr::multiply(factor,
b[current_row]);
146 const std::vector<size_t>& pivot_cols,
const std::vector<size_t>& pivot_rows,
149 (
context).limits().max_ast_nodes,
"transform");
150 size_t n = unknowns.size();
151 std::map<std::string, std::shared_ptr<SymbolicExpr>> solution;
153 std::set<size_t> pivot_col_set(pivot_cols.begin(), pivot_cols.end());
154 for (
size_t col = 0; col < n; ++col) {
155 if (pivot_col_set.find(col) == pivot_col_set.end()) {
157 solution[unknowns[col]] = SymbolicExpr::variable(unknowns[col]);
161 for (
size_t k = 0; k < pivot_cols.size(); ++k) {
162 size_t col = pivot_cols[k];
163 size_t row = pivot_rows[k];
167 for (
size_t j = col + 1; j < n; ++j) {
168 if (pivot_col_set.find(j) != pivot_col_set.end()) {
174 auto term = SymbolicExpr::multiply(coeff, SymbolicExpr::variable(unknowns[j]));
175 value = SymbolicExpr::add(
value, SymbolicExpr::multiply(term, SymbolicExpr::number(-1)));
179 auto pivot_val = A[row][col];
182 solution[unknowns[col]] =
value;
187std::vector<std::map<std::string, std::shared_ptr<SymbolicExpr>>>
188ParametricSolver::solve_linear_parametric(
189 const std::vector<std::shared_ptr<SymbolicExpr>>& equations,
190 const std::vector<std::string>& unknowns,
193 detail::RewriteBudget transform_budget(
context, (
context).limits().max_recursion_depth,
194 (
context).limits().max_ast_nodes,
"transform");
195 size_t m = equations.size();
196 size_t n = unknowns.size();
198 if (m == 0 || n == 0) {
200 std::map<std::string, std::shared_ptr<SymbolicExpr>> solution;
201 for (
const auto& var : unknowns) {
202 solution[var] = SymbolicExpr::variable(var);
207 std::vector<std::vector<std::shared_ptr<SymbolicExpr>>> A(m, std::vector<std::shared_ptr<SymbolicExpr>>(n));
208 std::vector<std::shared_ptr<SymbolicExpr>>
b(m);
210 for (
size_t i = 0; i < m; ++i) {
211 for (
size_t j = 0; j < n; ++j) {
219 std::vector<size_t> pivot_cols;
220 std::vector<size_t> pivot_rows;
221 size_t current_row = 0;
223 for (
size_t col = 0; col < n && current_row < m; ++col) {
226 if (pivot_row == m) {
230 if (pivot_row != current_row) {
231 std::swap(A[pivot_row], A[current_row]);
232 std::swap(
b[pivot_row],
b[current_row]);
237 pivot_cols.push_back(col);
238 pivot_rows.push_back(current_row);
242 for (
size_t r = current_row;
r < m; ++
r) {
255ParametricSolver::solve_polynomial_parametric_checked(
256 const std::vector<std::shared_ptr<SymbolicExpr>>& equations,
257 const std::vector<std::string>& unknowns,
258 const std::vector<std::string>& parameters,
261 constexpr const char*
operation =
"solve_polynomial_parametric";
262 if (equations.empty() || unknowns.empty()) {
265 "parametric polynomial solve requires equations and unknowns",
269 equations.size() * unknowns.size() + 1, operation);
274 if (is_linear_in_unknowns(equations, unknowns,
context))
275 return solve_linear_parametric(equations, unknowns,
context);
276 return solve_polynomial_parametric_impl(
277 equations, unknowns, parameters,
context);
280 }
catch (
const std::bad_alloc&) {
283 "allocation failed while solving parametric polynomial system",
285 }
catch (
const std::exception& ex) {
292ParametricSolver::solve_polynomial_parametric_checked(
293 const std::vector<std::shared_ptr<SymbolicExpr>>& equations,
294 const std::vector<std::string>& unknowns,
295 const std::vector<std::string>& parameters)
298 return solve_polynomial_parametric_checked(
299 equations, unknowns, parameters,
context);
302std::vector<std::map<std::string, std::shared_ptr<SymbolicExpr>>>
303ParametricSolver::solve_system(
304 const std::vector<std::shared_ptr<SymbolicExpr>>& equations,
305 const std::vector<std::string>& unknowns,
306 const std::vector<std::string>& parameters)
308 if (equations.empty() || unknowns.empty()) {
314 if (is_linear_in_unknowns(equations, unknowns,
context)) {
315 return solve_linear_parametric(equations, unknowns,
context);
317 auto solved = solve_polynomial_parametric_checked(
318 equations, unknowns, parameters,
context);
319 if (!solved)
throw solved.error();
320 return std::move(solved.value());
325 const std::vector<std::shared_ptr<SymbolicExpr>>& equations,
326 const std::vector<std::string>& unknowns,
327 const std::vector<std::string>& parameters)
330 if (equations.empty() || unknowns.empty())
return result;
331 auto solutions = solve_system(equations, unknowns, parameters);
332 if (!solutions.empty()) {
334 only_case.
condition = SymbolicExpr::number(1);
335 only_case.solutions = std::move(solutions);
336 result.cases.push_back(std::move(only_case));
static Result failure(CasErrc code, std::string message, std::string operation={})
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
Result< Tribool > query_nonzero_value(const Node &node, const FactsQuery &facts, Domain domain, ComputationContext &context)
const FactsQuery & no_facts() noexcept
ComputationContext const std::string & operation
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)
static Tribool parametric_nonzero_value(const std::shared_ptr< SymbolicExpr > &expression, ComputationContext &context)
ExprResult eq(const ExprPtr &lhs, const ExprPtr &rhs, ComputationContext &context)
static size_t find_parametric_pivot(ParametricMatrix &matrix, size_t row, size_t column, 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< SymbolicExpr > extract_coefficient(const std::shared_ptr< SymbolicExpr > &expr, const std::string &var, ComputationContext &context)
std::vector< std::vector< std::shared_ptr< SymbolicExpr > > > ParametricMatrix
@ Complex
Complex numbers (default, least specific)
static bool parametric_residual_zero(const std::shared_ptr< SymbolicExpr > &expression, ComputationContext &context)
Tribool
Tri-state logic value for property queries.
@ True
Property definitely holds
@ False
Property definitely does not hold
Result< ParametricSolutionList > ParametricSolutionsResult
static std::map< std::string, std::shared_ptr< SymbolicExpr > > parametric_linear_solution(const ParametricMatrix &A, const ParametricVector &b, const std::vector< size_t > &pivot_cols, const std::vector< size_t > &pivot_rows, const std::vector< std::string > &unknowns, ComputationContext &context)
std::vector< std::shared_ptr< SymbolicExpr > > ParametricVector
ResidualCheckResult check_zero_residual(const ExprPtr &residual, ComputationContext &context, const LMCAS::EqvOptions &options)
const std::string const ExprPtr & value
static void eliminate_parametric_column(ParametricMatrix &A, ParametricVector &b, size_t current_row, size_t col, size_t n, ComputationContext &context)
static std::shared_ptr< SymbolicExpr > extract_constant_term(const std::shared_ptr< SymbolicExpr > &expr, const std::vector< std::string > &unknowns, ComputationContext &context)
static bool parametric_zero(const std::shared_ptr< SymbolicExpr > &expression, ComputationContext &context)
含参方程组求解器 ParametricSolver,支持分段解。
std::shared_ptr< SymbolicExpr > condition
参数满足的条件表达式