LMCAS
Lamina Computer Algebra System
载入中...
搜索中...
未找到
complex_root_projection.cpp
浏览该文件的文档.
2
3#include <algorithm>
4#include <utility>
5
7
8Poly scale_poly(Poly polynomial, const Rational& scalar) {
9 for (auto& coefficient : polynomial.coeffs) {
10 coefficient = coefficient * scalar;
11 }
12 polynomial.trim();
13 return polynomial;
14}
15
17 BigInt common_denominator(1);
18 for (const auto& coefficient : polynomial.coeffs) {
19 common_denominator *= coefficient.get_denominator();
20 }
21 for (auto& coefficient : polynomial.coeffs) {
22 coefficient = Rational(
23 coefficient.get_numerator() *
24 (common_denominator / coefficient.get_denominator()));
25 }
26 polynomial.trim();
27 return polynomial;
28}
29
30namespace {
31
32using PolyMatrix = std::vector<std::vector<Poly>>;
33
35 std::vector<std::vector<Rational>> coefficients;
36
37 void add(std::size_t x_degree, std::size_t y_degree,
38 const Rational& coefficient) {
39 if (coefficient == Rational(0)) return;
40 if (coefficients.size() <= x_degree) {
41 coefficients.resize(x_degree + 1);
42 }
43 if (coefficients[x_degree].size() <= y_degree) {
44 coefficients[x_degree].resize(y_degree + 1, Rational(0));
45 }
46 coefficients[x_degree][y_degree] =
47 coefficients[x_degree][y_degree] + coefficient;
48 }
49};
50
55
56Poly constant_poly(const Rational& value, const std::string& variable) {
57 return Poly(std::vector<Rational>{value}, variable);
58}
59
61 const Poly& numerator,
62 const Poly& denominator,
64 const std::string& operation) {
65 auto step = context.consume_steps(1, operation);
66 if (!step) return Result<Poly>::failure(step.error());
67 if (denominator.is_zero()) {
70 "fraction-free resultant encountered a zero divisor",
71 operation);
72 }
73 auto division = numerator.div_mod(denominator);
74 if (!division.second.is_zero()) {
77 "fraction-free resultant division was not exact",
78 operation);
79 }
80 return Result<Poly>::success(std::move(division.first));
81}
82
84 BiPolynomial output;
85 for (std::size_t x = 0; x < input.coefficients.size(); ++x) {
86 for (std::size_t y = 0; y < input.coefficients[x].size(); ++y) {
87 output.add(x + 1, y, input.coefficients[x][y]);
88 }
89 }
90 return output;
91}
92
94 BiPolynomial output;
95 for (std::size_t x = 0; x < input.coefficients.size(); ++x) {
96 for (std::size_t y = 0; y < input.coefficients[x].size(); ++y) {
97 output.add(x, y + 1, input.coefficients[x][y]);
98 }
99 }
100 return output;
101}
102
103void add_scaled(BiPolynomial& destination,
104 const BiPolynomial& source,
105 const Rational& scalar) {
106 for (std::size_t x = 0; x < source.coefficients.size(); ++x) {
107 for (std::size_t y = 0; y < source.coefficients[x].size(); ++y) {
108 destination.add(x, y, source.coefficients[x][y] * scalar);
109 }
110 }
111}
112
114 BiPolynomial power_real;
115 power_real.add(0, 0, Rational(1));
116 BiPolynomial power_imaginary;
117 ComplexBivariate result;
118
119 for (std::size_t degree = 0; degree < polynomial.coeffs.size(); ++degree) {
120 add_scaled(result.real, power_real, polynomial.coeffs[degree]);
121 add_scaled(result.imaginary, power_imaginary,
122 polynomial.coeffs[degree]);
123
124 BiPolynomial next_real = shift_x(power_real);
125 add_scaled(next_real, shift_y(power_imaginary), Rational(-1));
126 BiPolynomial next_imaginary = shift_x(power_imaginary);
127 add_scaled(next_imaginary, shift_y(power_real), Rational(1));
128 power_real = std::move(next_real);
129 power_imaginary = std::move(next_imaginary);
130 }
131 return result;
132}
133
134std::vector<Poly> coefficients_in_y(
135 const BiPolynomial& polynomial,
136 const std::string& remaining_variable) {
137 std::size_t maximum_y = 0;
138 for (const auto& x_coefficients : polynomial.coefficients) {
139 if (!x_coefficients.empty()) {
140 maximum_y = std::max(maximum_y, x_coefficients.size() - 1);
141 }
142 }
143 std::vector<Poly> result(maximum_y + 1, Poly(remaining_variable));
144 for (std::size_t x = 0; x < polynomial.coefficients.size(); ++x) {
145 for (std::size_t y = 0; y < polynomial.coefficients[x].size(); ++y) {
146 if (result[y].coeffs.size() <= x) {
147 result[y].coeffs.resize(x + 1, Rational(0));
148 }
149 result[y].coeffs[x] = polynomial.coefficients[x][y];
150 }
151 }
152 while (result.size() > 1 && result.back().is_zero()) result.pop_back();
153 return result;
154}
155
156std::vector<Poly> coefficients_in_x(
157 const BiPolynomial& polynomial,
158 const std::string& remaining_variable) {
159 std::vector<Poly> result(
160 std::max<std::size_t>(1, polynomial.coefficients.size()),
161 Poly(remaining_variable));
162 for (std::size_t x = 0; x < polynomial.coefficients.size(); ++x) {
163 if (result[x].coeffs.size() < polynomial.coefficients[x].size()) {
164 result[x].coeffs.resize(
165 polynomial.coefficients[x].size(), Rational(0));
166 }
167 for (std::size_t y = 0; y < polynomial.coefficients[x].size(); ++y) {
168 result[x].coeffs[y] = polynomial.coefficients[x][y];
169 }
170 result[x].trim();
171 }
172 while (result.size() > 1 && result.back().is_zero()) result.pop_back();
173 return result;
174}
175
176PolyMatrix sylvester_matrix(const std::vector<Poly>& left,
177 const std::vector<Poly>& right,
178 const std::string& variable) {
179 const std::size_t left_degree = left.size() - 1;
180 const std::size_t right_degree = right.size() - 1;
181 const std::size_t size = left_degree + right_degree;
182 PolyMatrix matrix(size, std::vector<Poly>(size, Poly(variable)));
183 for (std::size_t row = 0; row < right_degree; ++row) {
184 for (std::size_t column = 0; column <= left_degree; ++column) {
185 matrix[row][row + column] = left[left_degree - column];
186 }
187 }
188 for (std::size_t row = 0; row < left_degree; ++row) {
189 for (std::size_t column = 0; column <= right_degree; ++column) {
190 matrix[right_degree + row][row + column] =
191 right[right_degree - column];
192 }
193 }
194 return matrix;
195}
196
198 PolyMatrix& matrix, std::size_t pivot, std::size_t row,
199 const Poly& previous, ComputationContext& context,
200 const std::string& operation) {
201 for (std::size_t column = pivot + 1; column < matrix.size(); ++column) {
202 Poly numerator = matrix[row][column] * matrix[pivot][pivot] -
203 matrix[row][pivot] * matrix[pivot][column];
204 if (pivot != 0) {
205 auto quotient = exact_poly_divide(
206 numerator, previous, context, operation);
207 if (!quotient) return Result<void>::failure(quotient.error());
208 matrix[row][column] = std::move(quotient.value());
209 } else {
210 matrix[row][column] = std::move(numerator);
211 }
212 }
213 matrix[row][pivot] = Poly(matrix[pivot][pivot].variable_name);
214 return Result<void>::success();
215}
216
218 PolyMatrix matrix, const std::string& variable,
219 ComputationContext& context, const std::string& operation) {
220 Poly previous = constant_poly(Rational(1), variable);
221 int determinant_sign = 1;
222 for (std::size_t pivot = 0; pivot + 1 < matrix.size(); ++pivot) {
223 auto step = context.consume_steps(1, operation);
224 if (!step) return Result<Poly>::failure(step.error());
225 std::size_t replacement = pivot;
226 while (replacement < matrix.size() && matrix[replacement][pivot].is_zero()) {
227 ++replacement;
228 }
229 if (replacement == matrix.size()) return Result<Poly>::success(Poly(variable));
230 if (replacement != pivot) {
231 std::swap(matrix[pivot], matrix[replacement]);
232 determinant_sign = -determinant_sign;
233 }
234 const Poly pivot_value = matrix[pivot][pivot];
235 for (std::size_t row = pivot + 1; row < matrix.size(); ++row) {
236 auto eliminated = eliminate_resultant_row(
237 matrix, pivot, row, previous, context, operation);
238 if (!eliminated) return Result<Poly>::failure(eliminated.error());
239 }
240 previous = pivot_value;
241 }
242 Poly determinant = std::move(matrix.back().back());
243 if (determinant_sign < 0) {
244 determinant = scale_poly(std::move(determinant), Rational(-1));
245 }
246 determinant.trim();
247 return Result<Poly>::success(std::move(determinant));
248}
249
250bool zero_projection_polynomial(const std::vector<Poly>& coefficients) {
251 if (coefficients.empty()) {
252 return true;
253 }
254 return coefficients.size() == 1 && coefficients[0].is_zero();
255}
256
258 std::vector<Poly> left, std::vector<Poly> right,
259 const std::string& variable, ComputationContext& context,
260 const std::string& operation) {
261 while (left.size() > 1 && left.back().is_zero()) {
262 left.pop_back();
263 }
264 while (right.size() > 1 && right.back().is_zero()) {
265 right.pop_back();
266 }
269 }
270 const std::size_t size = left.size() + right.size() - 2;
271 if (size == 0) {
272 return Result<Poly>::success(constant_poly(Rational(1), variable));
273 }
274 auto step = context.consume_steps(size * size + 1, operation);
275 if (!step) {
276 return Result<Poly>::failure(step.error());
277 }
280}
281
282}
283
285 const Poly& polynomial, ComputationContext& context,
286 const std::string& operation) {
287 const ComplexBivariate parts = complex_bivariate_parts(polynomial);
288 auto real = sylvester_resultant(
289 coefficients_in_y(parts.real, "_re"),
290 coefficients_in_y(parts.imaginary, "_re"),
291 "_re", context, operation + ".resultant.real");
293 auto imaginary = sylvester_resultant(
294 coefficients_in_x(parts.real, "_im"),
295 coefficients_in_x(parts.imaginary, "_im"),
296 "_im", context, operation + ".resultant.imaginary");
297 if (!imaginary) return Result<CoordinateProjections>::failure(imaginary.error());
298 if (real.value().degree() <= 0 || imaginary.value().degree() <= 0) {
301 "complex coordinate resultant was identically zero", operation);
302 }
304 real.value().square_free_part().make_monic(),
305 imaginary.value().square_free_part().make_monic()});
306}
307
308}
std::pair< Polynomial, Polynomial > div_mod(const Polynomial &other) const
多项式带余除法
std::vector< CoeffType > coeffs
系数数组,coeffs[i] 为 x^i 的系数
void trim()
去除高次零系数
CasError & error()
static Result failure(CasErrc code, std::string message, std::string operation={})
static Result success(T value)
std::vector< Poly > coefficients_in_y(const BiPolynomial &polynomial, const std::string &remaining_variable)
PolyMatrix sylvester_matrix(const std::vector< Poly > &left, const std::vector< Poly > &right, const std::string &variable)
Result< Poly > sylvester_resultant(std::vector< Poly > left, std::vector< Poly > right, const std::string &variable, ComputationContext &context, const std::string &operation)
Result< Poly > resultant_determinant(PolyMatrix matrix, const std::string &variable, ComputationContext &context, const std::string &operation)
void add_scaled(BiPolynomial &destination, const BiPolynomial &source, const Rational &scalar)
Result< Poly > exact_poly_divide(const Poly &numerator, const Poly &denominator, ComputationContext &context, const std::string &operation)
Result< void > eliminate_resultant_row(PolyMatrix &matrix, std::size_t pivot, std::size_t row, const Poly &previous, ComputationContext &context, const std::string &operation)
std::vector< Poly > coefficients_in_x(const BiPolynomial &polynomial, const std::string &remaining_variable)
Result< CoordinateProjections > coordinate_projections(const Poly &polynomial, ComputationContext &context, const std::string &operation)
Poly scale_poly(Poly polynomial, const Rational &scalar)
const std::string & variable
const std::string const SymbolicNodePtr & replacement
ComputationContext const std::string & operation
std::size_t std::size_t ComputationContext & context
ExprResult real(const ExprPtr &expression, ComputationContext &context)
const ExprPtr & right
const std::string const ExprPtr & value
const ExprPtr & denominator
void add(std::size_t x_degree, std::size_t y_degree, const Rational &coefficient)