LMCAS
Lamina Computer Algebra System
载入中...
搜索中...
未找到
multivariate_hensel.cpp
浏览该文件的文档.
1/**
2 * @file multivariate_factor.cpp
3 * @brief 多元多项式因式分解器实现.
4 */
7#include <algorithm>
8#include <climits>
9#include <cstdint>
10#include <cmath>
11#include <map>
12#include <set>
13#include <stdexcept>
15namespace LMCAS {
16static MultiPoly truncate_mod_var(const MultiPoly& poly, const std::string& var,
17 int degree_bound);
18static MultiPoly embed_hensel_terms(const MultiPoly& polynomial,
19 const std::vector<std::string>& variables) {
20 if (polynomial.variables() == variables) { return polynomial; }
21 if (polynomial.is_constant()) {
22 return MultiPoly(
23 polynomial.is_zero() ? Rational(0) : polynomial.terms().front().second,
24 variables);
25 }
26 std::vector<size_t> coordinates;
27 coordinates.reserve(polynomial.variables().size());
28 for (const auto& variable : polynomial.variables()) {
29 auto position = std::find(variables.begin(), variables.end(), variable);
30 if (position == variables.end()) {
31 throw std::invalid_argument("Hensel embedding: variable is absent from target ring");
32 }
33 coordinates.push_back(static_cast<size_t>(position - variables.begin()));
34 }
35 std::vector<MultiPoly::Term> terms;
36 terms.reserve(polynomial.terms().size());
37 for (const auto& term : polynomial.terms()) {
38 Monomial monomial(variables.size(), 0);
39 for (size_t i = 0; i < term.first.size(); ++i) {
40 monomial[coordinates[i]] = term.first[i];
41 }
42 terms.emplace_back(std::move(monomial), term.second);
43 }
44 return MultiPoly(std::move(terms), variables);
45}
46
47
48static std::vector<MultiPoly> embed_without_lifting(
49 const std::vector<Polynomial<Rational>>& univariate_factors,
50 const std::vector<std::string>& vars) {
51 std::vector<MultiPoly> result;
52 result.reserve(univariate_factors.size());
53 for (const auto& uf : univariate_factors) {
54 result.push_back(embed_hensel_terms(
55 MultiPoly::from_univariate(uf, uf.variable_name), vars));
56 }
57 return result;
58}
59
60
61static std::vector<MultiPoly> lifting_shift_powers(
62 const std::vector<std::string>& vars, int lift_var_idx,
63 const Rational& eval_point, int degree_bound) {
64 std::vector<MultiPoly> shift_powers;
65 shift_powers.reserve(degree_bound + 1);
66 shift_powers.push_back(MultiPoly(Rational(1), vars)); /**< 零次幂 (lift_var - eval_point)^0 = 1。 */
67 if (lift_var_idx >= 0) {
68 Monomial var_mono(vars.size(), 0);
69 var_mono[lift_var_idx] = 1;
70 std::vector<MultiPoly::Term> lin_terms;
71 lin_terms.emplace_back(var_mono, Rational(1));
72 if (!eval_point.is_zero()) {
73 Monomial const_mono(vars.size(), 0);
74 lin_terms.emplace_back(const_mono, -eval_point);
75 }
76 MultiPoly shift_lin(std::move(lin_terms), vars);
77 shift_powers.push_back(shift_lin);
78 for (int k = 2; k <= degree_bound; ++k) {
79 shift_powers.push_back(shift_powers[k - 1] * shift_lin);
80 }
81 } else {
82 for (int k = 1; k <= degree_bound; ++k) {
83 shift_powers.push_back(MultiPoly(Rational(1), vars));
84 }
85 }
86 return shift_powers;
87}
88
89static MultiPoly lifting_error_coefficient(const MultiPoly& error,
90 const std::string& lift_var, int lift_var_idx, const Rational& eval_point,
91 int k, const std::vector<MultiPoly>& shift_powers,
92 const std::vector<std::string>& vars) {
93 MultiPoly error_k;
94 if (eval_point.is_zero()) {
95 std::vector<MultiPoly::Term> error_k_terms;
96 for (const auto& term : error.terms()) {
97 const Monomial& mono = term.first;
98 int exp = (lift_var_idx >= 0 && static_cast<size_t>(lift_var_idx) < mono.size())
99 ? mono[lift_var_idx] : 0;
100 if (exp == k) {
101 Monomial reduced = mono;
102 reduced[lift_var_idx] = 0;
103 error_k_terms.emplace_back(std::move(reduced), term.second);
104 }
105 }
106 if (error_k_terms.empty()) { return MultiPoly(Rational(0), vars); }
107 error_k = MultiPoly(std::move(error_k_terms), vars);
108 } else {
109 /**
110 * @brief 逐次除以 (lift_var - eval_point),再在 eval_point 处求值。
111 * 得到 error / (lift_var - eval_point)^k 的值,
112 * 等价于 error 的 k 阶导数在该点的值除以 k!。
113 */
114 MultiPoly remainder = error;
115 for (int j = 0; j < k; ++j) {
116 MultiPoly eval_check = remainder.eval(lift_var, eval_point);
117 if (!eval_check.is_zero()) {
118 remainder = MultiPoly(Rational(0), vars);
119 break;
120 }
121 try {
122 remainder = remainder.exact_div(shift_powers[1]);
123 } catch (const std::runtime_error&) {
124 remainder = MultiPoly(Rational(0), vars);
125 break;
126 }
127 }
128 error_k = embed_hensel_terms(remainder.eval(lift_var, eval_point), vars);
129 if (error_k.is_zero()) { return error_k; }
130 }
131 return error_k;
132}
133
134static std::vector<MultiPoly> evaluated_lifting_cofactors(
135 const std::vector<MultiPoly>& factors, const std::string& lift_var,
136 const Rational& eval_point, const std::vector<std::string>& vars) {
137 const int r = static_cast<int>(factors.size());
138 std::vector<MultiPoly> cofactors;
139 cofactors.reserve(r);
140 for (int i = 0; i < r; ++i) {
141 MultiPoly cof(Rational(1), vars);
142 for (int j = 0; j < r; ++j) {
143 if (j == i) { continue; }
144 MultiPoly fj_eval = embed_hensel_terms(
145 factors[j].eval(lift_var, eval_point), vars);
146 cof = cof * fj_eval;
147 }
148 cofactors.push_back(cof);
149 }
150 return cofactors;
151}
152
153static bool lifting_residual_is_zero(const MultiPoly& verify_error,
154 int lift_var_idx, int k) {
155 if (verify_error.is_zero()) { return true; }
156 bool residual_ok = true;
157 for (const auto& term : verify_error.terms()) {
158 const Monomial& mono = term.first;
159 int exp = (lift_var_idx >= 0 &&
160 static_cast<size_t>(lift_var_idx) < mono.size())
161 ? mono[lift_var_idx] : 0;
162 if (exp <= k) {
163 residual_ok = false;
164 break;
165 }
166 }
167 return residual_ok;
168}
169
170static MultiPoly truncated_factor_product(const std::vector<MultiPoly>& factors,
171 const std::string& variable, int degree_bound) {
172 MultiPoly product = factors[0];
173 for (size_t i = 1; i < factors.size(); ++i) {
174 product = product * factors[i];
175 product = truncate_mod_var(product, variable, degree_bound);
176 }
177 return product;
178}
179
180static bool apply_hensel_lift_steps(const MultiPoly& poly,
181 std::vector<MultiPoly>& factors, const std::string& lift_var, int lift_var_idx,
182 const Rational& eval_point, int degree_bound, int factor_count) {
183 const auto& vars = poly.variables();
184 auto shift_powers = lifting_shift_powers(vars, lift_var_idx,
185 eval_point, degree_bound);
186 for (int k = 1; k <= degree_bound; ++k) {
187 MultiPoly product = truncated_factor_product(factors, lift_var, k + 1);
188 MultiPoly poly_trunc = truncate_mod_var(poly, lift_var, k + 1);
189 MultiPoly error = poly_trunc - product;
190 if (error.is_zero()) { continue; }
191 auto error_k = lifting_error_coefficient(error, lift_var, lift_var_idx,
192 eval_point, k, shift_powers, vars);
193 if (error_k.is_zero()) { continue; }
194 auto cofactors = evaluated_lifting_cofactors(factors, lift_var,
195 eval_point, vars);
196 std::vector<MultiPoly> corrections = multivariate_diophantine(
197 cofactors, error_k, lift_var, eval_point, k + 1);
198 if (corrections.size() != static_cast<size_t>(factor_count)) { return false; }
199 for (int i = 0; i < factor_count; ++i) {
200 if (corrections[i].is_zero()) { continue; }
201 MultiPoly correction_poly = corrections[i] * shift_powers[k];
202 factors[i] = factors[i] + correction_poly;
203 }
204 MultiPoly verify_product = truncated_factor_product(factors, lift_var, k + 1);
205 MultiPoly verify_error = poly_trunc - verify_product;
206 if (!lifting_residual_is_zero(verify_error, lift_var_idx, k)) { break; }
207 }
208 return true;
209}
210
211/**
212 * @brief 多元 Hensel 提升(单变量步)
213 *
214 * 将一元因子逐变量提升,从 f(x_1, a_2, ..., a_n) 的因子恢复到包含 lift_var 的因子.
215 * 每次引入一个辅助变量,计算修正项直到达到次数上界.
216 *
217 * 算法(参考 Geddes, Czapor, Labahn Section15.6):
218 * 1. 将一元因子嵌入到完整变量集中
219 * 2. 对 k = 1, ..., degree_bound:
220 * a. 计算当前因子乘积(截断到 lift_var 次数 <= k)
221 * b. 计算误差 E = poly - product(提取 lift_var 次数恰为 k 的部分)
222 * c. 若误差为零则继续
223 * d. 用丢番图求解器分配误差到各因子
224 * e. 将修正项加到各因子上
225 * f. 验证:product of lifted factors == poly mod (lift_var - eval_point)^(k+1)
226 * 3. 返回提升后的因子
227 *
228 * @param[in] poly 原始多元多项式
229 * @param[in] univariate_factors 一元分解得到的因子列表
230 * @param[in] lift_var 当前提升的变量名
231 * @param[in] eval_point 该变量的求值点
232 * @param[in] degree_bound 提升次数上界
233 * @return 提升后的多元因子列表
234 *
235 * @see Geddes, Czapor, Labahn. "Algorithms for Computer Algebra." Section15.6.
236 */
237std::vector<MultiPoly> multivariate_hensel_lift(
238 const MultiPoly& poly,
239 const std::vector<Polynomial<Rational>>& univariate_factors,
240 const std::string& lift_var,
241 const Rational& eval_point,
242 int degree_bound)
243{
244 int r = static_cast<int>(univariate_factors.size());
245 if (r == 0) { return {}; }
246 if (r == 1) {
247 return {poly};
248 }
249 if (degree_bound <= 0) {
250 return embed_without_lifting(univariate_factors, poly.variables());
251 }
252
253 const auto& vars = poly.variables();
254
255 /// 确定主变量(一元因子的变量)和提升变量在完整变量集中的位置
256 std::string main_var = univariate_factors[0].variable_name;
257 int lift_var_idx = -1;
258 for (size_t i = 0; i < vars.size(); ++i) {
259 if (vars[i] == lift_var) { lift_var_idx = static_cast<int>(i); }
260 }
261
262 for (const auto& factor : univariate_factors) {
263 if (factor.variable_name != main_var) {
264 throw std::invalid_argument("Hensel lifting: univariate factor ring mismatch");
265 }
266 }
267 auto factors = embed_without_lifting(univariate_factors, vars);
268
269 /// lift_var 位于变量域之外时,返回嵌入后的原因子.
270 if (lift_var_idx < 0) {
271 return factors;
272 }
273
274 MultiPoly base_product(Rational(1), vars);
275 for (const auto& factor : factors) { base_product = base_product * factor; }
276 if (base_product.eval(lift_var, eval_point) != poly.eval(lift_var, eval_point)) {
277 return {};
278 }
279
281 poly, factors, lift_var, lift_var_idx, eval_point, degree_bound, r)) {
282 return {};
283 }
284
285 return factors;
286}
287/**
288 * @internal
289 * @brief 一元多项式扩展 GCD(有理数域上)
290 *
291 * 给定 a, b in Q[x],计算 gcd(a, b) 及 Bezout 系数 s, t,
292 * 使得 s*a + t*b = gcd(a, b).
293 *
294 * @param[in] a 第一个多项式
295 * @param[in] b 第二个多项式
296 * @param[out] s Bezout 系数 s
297 * @param[out] t Bezout 系数 t
298 * @return gcd(a, b)
299 */
301 const Polynomial<Rational>& a,
302 const Polynomial<Rational>& b,
305{
306 std::string var = a.variable_name;
307
308 /// r0 = a, r1 = b
309 /// s0*a + t0*b = r0
310 /// s1*a + t1*b = r1
311 Polynomial<Rational> r0 = a, r1 = b;
312 Polynomial<Rational> s0({Rational(1)}, var), s1(var); // s0=1, s1=0
313 Polynomial<Rational> t0(var), t1({Rational(1)}, var); // t0=0, t1=1
314
315 while (!r1.is_zero()) {
316 auto [q, r] = r0.div_mod(r1);
317
318 Polynomial<Rational> r_new = r;
319 Polynomial<Rational> s_new = s0 - q * s1;
320 Polynomial<Rational> t_new = t0 - q * t1;
321
322 r0 = r1; r1 = r_new;
323 s0 = s1; s1 = s_new;
324 t0 = t1; t1 = t_new;
325 }
326
327 /// 归一化使 gcd 为首一多项式
328 if (!r0.is_zero()) {
329 Rational lc = r0.lead_coeff();
330 if (lc != Rational(1)) {
331 Rational inv = Rational(1) / lc;
332 for (auto& c : r0.coeffs) c = c * inv;
333 for (auto& c : s0.coeffs) c = c * inv;
334 for (auto& c : t0.coeffs) c = c * inv;
335 }
336 }
337
338 s = s0;
339 t = t0;
340 return r0;
341}
342
343/**
344 * @internal
345 * @brief 将 MultiPoly 截断为关于指定变量次数 < degree_bound 的部分
346 *
347 * 保留所有项中指定变量指数严格小于 degree_bound 的项.
348 *
349 * @param[in] poly 输入多项式
350 * @param[in] var 变量名
351 * @param[in] degree_bound 次数上界(保留 < degree_bound 的项)
352 * @return 截断后的多项式
353 */
354static MultiPoly truncate_mod_var(const MultiPoly& poly, const std::string& var,
355 int degree_bound)
356{
357 if (poly.is_zero()) { return poly; }
358
359 const auto& vars = poly.variables();
360 int var_idx = -1;
361 for (size_t i = 0; i < vars.size(); ++i) {
362 if (vars[i] == var) { var_idx = static_cast<int>(i); break; }
363 }
364 /// 若变量不在列表中,多项式不含该变量,无需截断
365 if (var_idx < 0) { return poly; }
366
367 std::vector<MultiPoly::Term> result_terms;
368 for (const auto& term : poly.terms()) {
369 const Monomial& mono = term.first;
370 int exp = (static_cast<size_t>(var_idx) < mono.size()) ? mono[var_idx] : 0;
371 if (exp < degree_bound) {
372 result_terms.push_back(term);
373 }
374 }
375
376 if (result_terms.empty()) { return MultiPoly(Rational(0), vars); }
377 return MultiPoly(std::move(result_terms), vars);
378}
379
381 const std::vector<MultiPoly>& factors, const std::string& var,
382 const Rational& eval_point, Polynomial<Rational>& f1_uni,
383 Polynomial<Rational>& f2_uni) {
384 bool converted = false;
385
386 try {
387 f1_uni = factors[0].to_univariate();
388 f2_uni = factors[1].to_univariate();
389 converted = true;
390 } catch (const std::invalid_argument&) {
391 try {
392 MultiPoly f1_eval = factors[0].eval(var, eval_point);
393 MultiPoly f2_eval = factors[1].eval(var, eval_point);
394 f1_uni = f1_eval.to_univariate();
395 f2_uni = f2_eval.to_univariate();
396 converted = true;
397 } catch (const std::invalid_argument&) {
398 converted = false;
399 }
400 }
401 if (converted && f1_uni.variable_name != f2_uni.variable_name) {
402 /**
403 * @brief 常数转换的默认变量名不代表其系数环。
404 * 仅常数可嵌入另一变量环;不同活跃变量须保持区分。
405 */
406 if (f1_uni.degree() <= 0) {
407 f1_uni = Polynomial<Rational>(f1_uni.coeffs, f2_uni.variable_name);
408 } else if (f2_uni.degree() <= 0) {
409 f2_uni = Polynomial<Rational>(f2_uni.coeffs, f1_uni.variable_name);
410 } else {
411 return false;
412 }
413 }
414 return converted;
415}
416
417static bool diophantine_target(const MultiPoly& target,
418 const std::string& var, const Rational& eval_point,
419 const std::string& main_var, Polynomial<Rational>& target_uni) {
420 try {
421 target_uni = target.to_univariate();
422 /**
423 * @brief 同一一元变量域内可直接转换。
424 * 仅含提升变量的目标须先在提升点求值。
425 */
426 if (target_uni.degree() > 0 &&
427 target_uni.variable_name != main_var) {
428 throw std::logic_error("target uses the lift variable");
429 }
430 } catch (const std::logic_error&) {
431 try {
432 MultiPoly target_eval = target.eval(var, eval_point);
433 target_uni = target_eval.to_univariate();
434 } catch (const std::invalid_argument&) {
435 if (target.is_constant()) {
436 Rational c = target.is_zero() ? Rational(0) : target.terms()[0].second;
437 target_uni = Polynomial<Rational>({c}, main_var);
438 } else {
439 return false;
440 }
441 }
442 }
443 if (target_uni.degree() <= 0) {
444 target_uni.variable_name = main_var;
445 } else if (target_uni.variable_name != main_var) {
446 return false;
447 }
448 return true;
449}
450
451static std::vector<MultiPoly> solve_diophantine_pair(
452 const std::vector<MultiPoly>& factors, const MultiPoly& target,
453 const std::string& var, const Rational& eval_point, int degree_bound) {
454 const auto& vars = factors[0].variables();
455 Polynomial<Rational> f1_uni, f2_uni;
456 if (!diophantine_univariate_factors(factors, var, eval_point,
457 f1_uni, f2_uni)) {
458 return {MultiPoly(Rational(0), vars), MultiPoly(Rational(0), vars)};
459 }
460 Polynomial<Rational> s_coeff, t_coeff;
461 Polynomial<Rational> g = extended_gcd_poly(f1_uni, f2_uni, s_coeff, t_coeff);
462
463 Polynomial<Rational> target_uni;
464 if (!diophantine_target(target, var, eval_point,
465 f1_uni.variable_name, target_uni)) {
466 return {MultiPoly(Rational(0), vars), MultiPoly(Rational(0), vars)};
467 }
468
469
470 /**
471 * @brief 用 target/gcd 缩放 Bézout 系数,兼容 gcd 非 1 的情形。
472 * 互素因子的 gcd 为 1;s_1 = s*(target/gcd),s_2 = t*(target/gcd)。
473 */
475 if (g.is_zero() || g.degree() < 0) {
476 return {MultiPoly(Rational(0), vars), MultiPoly(Rational(0), vars)};
477 }
478
479 auto [quotient, remainder] = target_uni.div_mod(g);
480 if (!remainder.is_zero()) {
481 return {MultiPoly(Rational(0), vars), MultiPoly(Rational(0), vars)};
482 }
483
484 Polynomial<Rational> s1_uni = s_coeff * quotient;
485 Polynomial<Rational> s2_uni = t_coeff * quotient;
486
487 /**
488 * @brief 按 f_2、f_1 约化系数并保持 s_1*f_1 + s_2*f_2 = target。
489 * 次数约束为 deg(s_1) < deg(f_2)、deg(s_2) < deg(f_1)。
490 */
491 if (!f2_uni.is_zero() && s1_uni.degree() >= f2_uni.degree()) {
492 auto [q1, r1] = s1_uni.div_mod(f2_uni);
493 s1_uni = r1;
494 s2_uni = s2_uni + q1 * f1_uni;
495 }
496 if (!(s1_uni * f1_uni + s2_uni * f2_uni == target_uni)) { return {}; }
497
498 std::string uni_var = f1_uni.variable_name;
499 MultiPoly s1_mp = embed_hensel_terms(
500 MultiPoly::from_univariate(s1_uni, uni_var), vars);
501 MultiPoly s2_mp = embed_hensel_terms(
502 MultiPoly::from_univariate(s2_uni, uni_var), vars);
503 s1_mp = truncate_mod_var(s1_mp, var, degree_bound);
504 s2_mp = truncate_mod_var(s2_mp, var, degree_bound);
505
506 return {s1_mp, s2_mp};
507}
508/**
509 * @brief 多元丢番图方程求解器
510 *
511 * 求解 s_1*f_1 + s_2*f_2 + ... + sᵣ*fᵣ == target (mod (var - eval_point)^degree_bound),
512 * 其中各 fᵢ 两两互素.用于 Hensel 提升过程中计算修正项.
513 *
514 * 算法:
515 * 1. 二因子情形(r=2):使用扩展 GCD 求 Bezout 系数
516 * 2. 一般情形(r>2):递归归约--令 g = f_2*...*fᵣ,
517 * 先解 s_1*f_1 + t*g == target,再递归解 s_2*f_2 + ... + sᵣ*fᵣ == t
518 * 3. 对每个解截断为关于 var 的次数 < degree_bound
519 *
520 * @param[in] factors 互素因子列表 [f_1, ..., fᵣ]
521 * @param[in] target 目标多项式 c
522 * @param[in] var 变量名
523 * @param[in] eval_point 求值点
524 * @param[in] degree_bound 次数上界
525 * @return 解多项式列表 [s_1, s_2, ..., sᵣ]
526 *
527 * @see Geddes, Czapor, Labahn. "Algorithms for Computer Algebra." Section15.5.
528 */
529std::vector<MultiPoly> multivariate_diophantine(
530 const std::vector<MultiPoly>& factors,
531 const MultiPoly& target,
532 const std::string& var,
533 const Rational& eval_point,
534 int degree_bound)
535{
536 int r = static_cast<int>(factors.size());
537 if (r == 0) { return {}; }
538 if (r == 1) {
539 /// 单因子情形:s_1 = target / f_1(精确除法后截断)
540 try {
541 MultiPoly s1 = target.exact_div(factors[0]);
542 s1 = truncate_mod_var(s1, var, degree_bound);
543 return {s1};
544 } catch (const std::runtime_error&) {
545 return {};
546 }
547 }
548
549 const auto& vars = factors[0].variables();
550
551 if (r == 2) {
552 return solve_diophantine_pair(factors, target, var, eval_point,
553 degree_bound);
554 }
555
556 /// 一般情形(r > 2):递归归约
557 /// 令 g = f_2 * f₃ * ... * fᵣ
558 MultiPoly g = factors[1];
559 for (int i = 2; i < r; ++i) {
560 g = g * factors[i];
561 }
562
563 /// 解二因子方程:s_1*f_1 + t*g == target
564 std::vector<MultiPoly> two_factors = {factors[0], g};
565 std::vector<MultiPoly> two_solution = multivariate_diophantine(
566 two_factors, target, var, eval_point, degree_bound);
567
568 if (two_solution.size() != 2) {
569 /// 退化情形
570 std::vector<MultiPoly> result(r, MultiPoly(Rational(0), vars));
571 return result;
572 }
573
574 /// s_1 已确定
575 MultiPoly s1 = two_solution[0];
576 MultiPoly t_poly = two_solution[1];
577
578 /// 递归解:s_2*f_2 + ... + sᵣ*fᵣ == t_poly * g
579 /// 因为原方程为 s_1*f_1 + t*g = target,
580 /// 我们需要 s_2*f_2 + ... + sᵣ*fᵣ = t*g = target - s_1*f_1
581 MultiPoly remaining_target = t_poly * g;
582 remaining_target = truncate_mod_var(remaining_target, var, degree_bound);
583
584 std::vector<MultiPoly> remaining_factors(factors.begin() + 1, factors.end());
585 std::vector<MultiPoly> remaining_solution = multivariate_diophantine(
586 remaining_factors, remaining_target, var, eval_point, degree_bound);
587
588 /// 组装完整解
589 std::vector<MultiPoly> result;
590 result.push_back(std::move(s1));
591 for (auto& sol : remaining_solution) {
592 result.push_back(std::move(sol));
593 }
594
595 return result;
596}
597
598} // namespace LMCAS
一元多项式模板类
std::pair< Polynomial, Polynomial > div_mod(const Polynomial &other) const
多项式带余除法
std::string variable_name
变量名
bool is_zero() const
判断是否为零多项式
std::vector< CoeffType > coeffs
系数数组,coeffs[i] 为 x^i 的系数
CoeffType lead_coeff() const
获取首项系数
int degree() const
获取多项式的次数
多元多项式因式分解器公共 API。
static std::vector< MultiPoly > solve_diophantine_pair(const std::vector< MultiPoly > &factors, const MultiPoly &target, const std::string &var, const Rational &eval_point, int degree_bound)
const std::string & variable
ExprResult exp(const ExprPtr &expression, ComputationContext &context)
std::vector< int > Monomial
单项式类型,以整数向量表示各变量的指数
__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
static bool diophantine_univariate_factors(const std::vector< MultiPoly > &factors, const std::string &var, const Rational &eval_point, Polynomial< Rational > &f1_uni, Polynomial< Rational > &f2_uni)
__attribute__((visibility("default"))) VectorCalculusFieldResult gradient_checked(const std __attribute__((visibility("default"))) VectorCalculusFieldResult gradient_checked(const std __attribute__((visibility("default"))) VectorField gradient(const std const std::vector< std::string > & vars
static MultiPoly truncate_mod_var(const MultiPoly &poly, const std::string &var, int degree_bound)
将 MultiPoly 截断为关于指定变量次数 < degree_bound 的部分
static Polynomial< Rational > extended_gcd_poly(const Polynomial< Rational > &a, const Polynomial< Rational > &b, Polynomial< Rational > &s, Polynomial< Rational > &t)
一元多项式扩展 GCD(有理数域上)
const VectorField const VectorField & c
static std::vector< MultiPoly > lifting_shift_powers(const std::vector< std::string > &vars, int lift_var_idx, const Rational &eval_point, int degree_bound)
static MultiPoly truncated_factor_product(const std::vector< MultiPoly > &factors, const std::string &variable, int degree_bound)
const MultiPoly & b
static bool lifting_residual_is_zero(const MultiPoly &verify_error, int lift_var_idx, int k)
std::vector< MultiPoly > multivariate_hensel_lift(const MultiPoly &poly, const std::vector< Polynomial< Rational > > &univariate_factors, const std::string &lift_var, const Rational &eval_point, int degree_bound)
多元 Hensel 提升(单变量步)
static MultiPoly lifting_error_coefficient(const MultiPoly &error, const std::string &lift_var, int lift_var_idx, const Rational &eval_point, int k, const std::vector< MultiPoly > &shift_powers, const std::vector< std::string > &vars)
static bool diophantine_target(const MultiPoly &target, const std::string &var, const Rational &eval_point, const std::string &main_var, Polynomial< Rational > &target_uni)
__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 apply_hensel_lift_steps(const MultiPoly &poly, std::vector< MultiPoly > &factors, const std::string &lift_var, int lift_var_idx, const Rational &eval_point, int degree_bound, int factor_count)
const ExprPtr & target
static std::vector< MultiPoly > embed_without_lifting(const std::vector< Polynomial< Rational > > &univariate_factors, const std::vector< std::string > &vars)
std::vector< MultiPoly > multivariate_diophantine(const std::vector< MultiPoly > &factors, const MultiPoly &target, const std::string &var, const Rational &eval_point, int degree_bound)
多元丢番图方程求解器
static MultiPoly embed_hensel_terms(const MultiPoly &polynomial, const std::vector< std::string > &variables)
__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 & t
const std::string & main_var
static std::vector< MultiPoly > evaluated_lifting_cofactors(const std::vector< MultiPoly > &factors, const std::string &lift_var, const Rational &eval_point, const std::vector< std::string > &vars)
混合超越方程不可约因式分解器公共 API.