12template <
typename Entry>
14 std::size_t coefficient_columns,
15 const std::vector<std::optional<std::size_t>>& pivot_row, Entry entry) {
16 std::vector<std::size_t> free_columns;
17 for (std::size_t column = 0; column < coefficient_columns; ++column) {
18 if (!pivot_row[column]) free_columns.push_back(column);
20 std::vector<ExprPtr> particular(
21 coefficient_columns, SymbolicExpr::number(0));
22 for (std::size_t column = 0; column < coefficient_columns; ++column) {
23 if (pivot_row[column]) {
24 particular[column] = entry(*pivot_row[column], coefficient_columns,
false);
27 if (free_columns.empty()) {
32 std::vector<std::vector<ExprPtr>>
basis;
33 basis.reserve(free_columns.size());
34 for (
const auto free_column : free_columns) {
35 std::vector<ExprPtr> vector(
36 coefficient_columns, SymbolicExpr::number(0));
37 vector[free_column] = SymbolicExpr::number(1);
38 for (std::size_t column = 0; column < coefficient_columns; ++column) {
39 if (pivot_row[column]) {
40 vector[column] = entry(*pivot_row[column], free_column,
true);
43 basis.push_back(std::move(vector));
46 std::move(particular), std::move(
basis), std::move(free_columns)});
52 for (std::size_t row = 0; row < rref.
rows; ++row) {
53 bool coefficients_zero =
true;
54 for (std::size_t column = 0; column < coefficient_columns; ++column) {
60 "linear-system consistency is not provable",
operation);
62 coefficients_zero = coefficients_zero && proof.value() ==
ZeroProof::Zero;
64 if (!coefficients_zero)
continue;
71 "linear-system right-hand side is not provably zero",
operation);
82 std::size_t coefficient_columns,
90 std::vector<Rational> matrix;
91 matrix.reserve(augmented.
entries.size());
92 for (
const auto& entry : augmented.
entries) {
97 "rational specialization received a symbolic entry",
100 matrix.push_back(*
value);
103 augmented.
rows, coefficient_columns, matrix,
false);
108 [&](std::size_t row, std::size_t column,
bool negate) {
109 const auto&
value = matrix[row * augmented.
cols + column];
118 std::size_t coefficient_columns,
124 if (augmented.
cols != coefficient_columns + 1) {
127 "linear solve requires one augmented right-hand side",
operation);
129 bool all_rational =
true;
130 for (
const auto& entry : augmented.
entries) {
134 return rational_linear_solve(
138 std::move(augmented), coefficient_columns,
141 auto& rref = eliminated.value().matrix;
143 auto inconsistent = inconsistent_symbolic_system(
146 if (inconsistent.value()) {
149 std::vector<std::optional<std::size_t>> pivot_row(coefficient_columns);
150 for (std::size_t index = 0;
151 index < eliminated.value().pivot_columns.size(); ++index) {
152 const auto column = eliminated.value().pivot_columns[index];
153 if (column < coefficient_columns) pivot_row[column] = index;
155 return assemble_linear_solution(coefficient_columns, pivot_row,
156 [&](std::size_t row, std::size_t column,
bool negate) {
157 const auto&
value = rref.at(row, column);
170 const std::size_t columns = coefficients.
cols;
172 std::move(coefficients), columns,
178 std::set<std::size_t> pivots(
179 eliminated.value().pivot_columns.begin(),
180 eliminated.value().pivot_columns.end());
181 std::vector<std::vector<ExprPtr>>
basis;
182 for (std::size_t free_column = 0; free_column < columns; ++free_column) {
183 if (pivots.count(free_column) != 0)
continue;
184 std::vector<ExprPtr> vector(columns, SymbolicExpr::number(0));
185 vector[free_column] = SymbolicExpr::number(1);
186 for (std::size_t row = 0;
187 row < eliminated.value().pivot_columns.size(); ++row) {
188 vector[eliminated.value().pivot_columns[row]] =
exact_negate(
189 eliminated.value().matrix.at(row, free_column),
context);
191 basis.push_back(std::move(vector));
static Result failure(CasErrc code, std::string message, std::string operation={})
static Result success(T value)
Result< bool > inconsistent_symbolic_system(const ExactMatrixData &rref, std::size_t coefficient_columns, ComputationContext &context, const std::string &operation)
Result< ExactLinearSolution > assemble_linear_solution(std::size_t coefficient_columns, const std::vector< std::optional< std::size_t > > &pivot_row, Entry entry)
Result< ExactLinearSolution > rational_linear_solve(const ExactMatrixData &augmented, std::size_t coefficient_columns, ComputationContext &context, const std::string &operation)
std::optional< Rational > exact_rational(const ExprPtr &expression)
ExprPtr exact_negate(const ExprPtr &expression, ComputationContext &context)
Result< void > validate_matrix(const ExactMatrixData &matrix, const std::string &operation)
Result< std::vector< std::vector< ExprPtr > > > nullspace_exact(ExactMatrixData coefficients, ComputationContext &context, const std::string &operation)
Result< EliminationResult > eliminate_exact(ExactMatrixData input, std::size_t coefficient_columns, EliminationForm form, ComputationContext &context, const std::string &operation)
Result< ZeroProof > classify_exact_zero(const ExprPtr &expression, ComputationContext &context, const std::string &operation)
bool rational_system_inconsistent(std::size_t rows, std::size_t coefficient_columns, const std::vector< Rational > &matrix)
Result< ExactLinearSolution > solve_linear_exact(ExactMatrixData augmented, std::size_t coefficient_columns, ComputationContext &context, const std::string &operation)
ComputationContext const std::string & operation
std::size_t std::size_t ComputationContext & context
std::vector< std::optional< std::size_t > > reduce_rational_rows(std::size_t rows, std::size_t coefficient_columns, std::vector< Rational > &matrix, bool start_at_pivot)
std::shared_ptr< SymbolicExpr > negate(const std::shared_ptr< SymbolicExpr > &expr)
const std::vector< FGLMPoly > & basis
const std::string const ExprPtr & value
const ExprPtr & at(std::size_t row, std::size_t col) const
std::vector< ExprPtr > entries