LMCAS
Lamina Computer Algebra System
载入中...
搜索中...
未找到
multivariate_factor_checked.cpp
浏览该文件的文档.
3#include <algorithm>
4#include <map>
5#include <new>
6#include <optional>
7#include <utility>
8
9namespace LMCAS {
11
13 const MultiPoly& raw, int multiplicity) {
14 if (multiplicity <= 0) {
16 "因子重数必须为正", "factor_multivariate");
17 }
18 if (raw.is_zero() || raw.is_constant()) return Result<void>::success();
19 MultiPoly factor = raw.make_primitive();
20 if (!factor.terms().empty() && factor.terms()[0].second < Rational(0)) {
21 factor = factor * Rational(-1);
22 }
23 auto existing = std::find(result.factors.begin(), result.factors.end(), factor);
24 if (existing == result.factors.end()) {
25 result.factors.push_back(std::move(factor));
26 result.multiplicities.push_back(multiplicity);
27 } else {
28 const auto index = static_cast<size_t>(existing - result.factors.begin());
29 result.multiplicities[index] += multiplicity;
30 }
31 return Result<void>::success();
32}
33
35 const MultiPoly& original,
36 const std::vector<MultiPoly>& raw_factors,
37 const std::vector<int>& raw_multiplicities,
38 Completeness completeness,
39 std::string reason)
40{
41 constexpr const char* operation = "factor_multivariate";
42 if (original.is_zero()) {
43 if (!raw_factors.empty()) {
45 CasErrc::InternalInvariant, "零多项式收到非空因子列表", operation);
46 }
49 MultiFactorResult{Rational(0), {}, {}},
50 completeness, std::move(reason)});
51 }
52
53 MultiFactorResult result;
54 for (size_t i = 0; i < raw_factors.size(); ++i) {
55 const int multiplicity = i < raw_multiplicities.size() ? raw_multiplicities[i] : 1;
56 auto appended = append_primitive_factor(result, raw_factors[i], multiplicity);
57 if (!appended) return MultiFactorCheckedResult::failure(appended.error());
58 }
59 MultiPoly product(Rational(1), original.variables());
60 for (size_t i = 0; i < result.factors.size(); ++i) {
61 for (int power = 0; power < result.multiplicities[i]; ++power) {
62 product = product * result.factors[i];
63 }
64 }
65 MultiPoly quotient = original.exact_div(product);
66 if (!quotient.is_constant() || quotient.terms().empty()) {
69 "因子乘积与输入只差常数的不变量失效", operation);
70 }
71 result.constant = quotient.terms()[0].second;
72 if (product * result.constant != original) {
74 CasErrc::InternalInvariant, "最终因子未精确重构输入", operation);
75 }
78 std::move(result), completeness, std::move(reason)});
79}
80
81}
82
83namespace {
84using namespace multivariate_checked_detail;
85
90
91static MultiPoly embed_univariate_factor(
92 const Polynomial<Rational>& factor,
93 const std::vector<std::string>& variables,
94 const std::string& main_variable)
95{
96 size_t main_index = variables.size();
97 for (size_t i = 0; i < variables.size(); ++i) {
98 if (variables[i] == main_variable) {
99 main_index = i;
100 break;
101 }
102 }
103 std::vector<MultiPoly::Term> terms;
104 for (size_t degree = 0; degree < factor.coeffs.size(); ++degree) {
105 if (factor.coeffs[degree].is_zero()) continue;
106 Monomial monomial(variables.size(), 0);
107 monomial[main_index] = static_cast<int>(degree);
108 terms.emplace_back(std::move(monomial), factor.coeffs[degree]);
109 }
110 return MultiPoly(std::move(terms), variables);
111}
112
113static MultiFactorCheckedResult factor_multivariate_impl(
114 const MultiPoly& poly, ComputationContext& context);
115
117 const MultiPoly& poly, const Monomial& common_monomial,
118 const MultiPoly& quotient, ComputationContext& context) {
119 const auto& variables = poly.variables();
120 auto sub = factor_multivariate_impl(quotient, context);
121 if (!sub) return sub;
122 std::vector<MultiPoly> factors;
123 std::vector<int> multiplicities;
124 for (size_t i = 0; i < common_monomial.size(); ++i) {
125 if (common_monomial[i] <= 0) continue;
126 Monomial monomial(variables.size(), 0);
127 monomial[i] = 1;
128 factors.emplace_back(
129 std::vector<MultiPoly::Term>{{monomial, Rational(1)}},
130 variables);
131 multiplicities.push_back(common_monomial[i]);
132 }
133 auto sub_value = std::move(sub.value());
134 factors.insert(factors.end(),
135 sub_value.value.factors.begin(),
136 sub_value.value.factors.end());
137 multiplicities.insert(multiplicities.end(),
138 sub_value.value.multiplicities.begin(),
139 sub_value.value.multiplicities.end());
141 poly, factors, multiplicities, sub_value.completeness,
142 std::move(sub_value.reason));
143}
144
146 const MultiPoly& poly, const std::pair<MultiPoly, MultiPoly>& difference,
148 std::vector<MultiPoly> factors;
149 std::vector<int> multiplicities;
151 std::string reason;
152 for (MultiPoly candidate :
153 {difference.first + difference.second,
154 difference.first - difference.second}) {
155 auto sub = factor_multivariate_impl(candidate, context);
156 if (!sub) return sub;
157 auto sub_value = std::move(sub.value());
158 if (sub_value.completeness == Completeness::Inconclusive) {
159 completeness = Completeness::Inconclusive;
160 if (reason.empty()) reason = sub_value.reason;
161 }
162 factors.insert(factors.end(),
163 sub_value.value.factors.begin(),
164 sub_value.value.factors.end());
165 multiplicities.insert(
166 multiplicities.end(),
167 sub_value.value.multiplicities.begin(),
168 sub_value.value.multiplicities.end());
169 }
171 poly, factors, multiplicities, completeness, std::move(reason));
172}
173
175 const MultiPoly& poly, const MultiPoly& primitive,
176 const std::string& left_variable, const std::string& right_variable,
178 const auto& variables = poly.variables();
179 size_t left_index = 0;
180 size_t right_index = 0;
181 for (size_t i = 0; i < variables.size(); ++i) {
182 if (variables[i] == left_variable) left_index = i;
183 if (variables[i] == right_variable) right_index = i;
184 }
185 Monomial left_monomial(variables.size(), 0);
186 Monomial right_monomial(variables.size(), 0);
187 left_monomial[left_index] = 1;
188 right_monomial[right_index] = 1;
189 MultiPoly linear(
190 std::vector<MultiPoly::Term>{
191 {left_monomial, Rational(1)},
192 {right_monomial, Rational(-1)}},
193 variables);
194 MultiPoly remaining = primitive.exact_div(linear);
195 auto sub = factor_multivariate_impl(remaining, context);
196 if (!sub) return sub;
197 auto sub_value = std::move(sub.value());
198 std::vector<MultiPoly> factors = {linear};
199 std::vector<int> multiplicities = {1};
200 factors.insert(factors.end(),
201 sub_value.value.factors.begin(),
202 sub_value.value.factors.end());
203 multiplicities.insert(multiplicities.end(),
204 sub_value.value.multiplicities.begin(),
205 sub_value.value.multiplicities.end());
207 poly, factors, multiplicities, sub_value.completeness,
208 std::move(sub_value.reason));
209}
210
212 const MultiPoly& poly, const MultiPoly& primitive,
213 const std::string& main_variable, ComputationContext& context) {
214 const auto& variables = poly.variables();
215 Polynomial<Rational> univariate = primitive.to_univariate();
216 auto factored =
218 if (!factored) {
219 return MultiFactorCheckedResult::failure(factored.error());
220 }
221 auto factor_value = std::move(factored.value());
222 std::vector<MultiPoly> factors;
223 factors.reserve(factor_value.value.size());
224 for (const auto& factor : factor_value.value) {
225 factors.push_back(embed_univariate_factor(
226 factor, variables, main_variable));
227 }
229 poly, factors, std::vector<int>(factors.size(), 1),
230 factor_value.completeness, std::move(factor_value.reason));
231}
232
234 const MultiPoly& poly,
236{
237 constexpr const char* operation = "factor_multivariate";
238 auto recursion = context.enter_recursion(operation);
239 if (!recursion) return MultiFactorCheckedResult::failure(recursion.error());
240 FactorRecursionGuard recursion_guard{context};
241
242 if (poly.is_zero()) {
244 poly, {}, {}, Completeness::Complete, {});
245 }
246 if (poly.is_constant()) {
248 poly, {}, {}, Completeness::Complete, {});
249 }
250 const auto& variables = poly.variables();
251 if (variables.empty()) {
254 "非常数多项式缺少变量表", operation);
255 }
256
257 std::string main_variable = variables.front();
258 for (const auto& variable : variables) {
259 if (poly.degree(variable) > poly.degree(main_variable)) {
260 main_variable = variable;
261 }
262 }
263 if (poly.total_degree() <= 1) {
265 poly, {poly}, {1}, Completeness::Complete, {});
266 }
267
268 auto [common_monomial, quotient] =
270 const bool has_common_monomial = std::any_of(
271 common_monomial.begin(), common_monomial.end(),
272 [](int exponent) { return exponent > 0; });
273 if (has_common_monomial) {
274 return factor_common_monomial(poly, common_monomial, quotient, context);
275 }
276 MultiPoly primitive = poly.make_primitive();
277 if (auto difference = detail::detect_difference_of_squares(primitive)) {
278 return factor_difference_of_squares(poly, *difference, context);
279 }
280 if (auto binomial = detail::detect_binomial_power(primitive)) {
281 const auto& [left, right, exponent] = *binomial;
282 (void)exponent;
283 return factor_binomial_power(poly, primitive, left, right, context);
284 }
285 if (primitive.is_univariate()) {
286 return factor_embedded_univariate(poly, primitive, main_variable, context);
287 }
288 auto evaluated = factor_evaluated_linear(poly, primitive, main_variable, context);
289 if (evaluated) return std::move(*evaluated);
290 auto homogeneous =
292 if (!homogeneous) {
293 return MultiFactorCheckedResult::failure(homogeneous.error());
294 }
295 if (homogeneous.value()) {
296 auto& result = *homogeneous.value();
298 poly, result.factors, result.multiplicities,
300 }
301
303 poly, {poly}, {1}, Completeness::Inconclusive,
304 "当前受检算法无法证明该多项式不可约");
305}
306
307}
308
310 const MultiPoly& poly,
312{
313 try {
314 auto factored = factor_multivariate_impl(poly, context);
315 if (factored && factored.value().completeness == Completeness::Inconclusive) {
317 poly, {poly}, {1}, Completeness::Inconclusive,
318 std::move(factored.value().reason));
319 }
320 return factored;
321 } catch (const std::bad_alloc&) {
323 CasErrc::ResourceLimit, "多元分解分配失败",
324 "factor_multivariate");
325 } catch (const std::exception& error) {
327 CasErrc::InternalInvariant, error.what(),
328 "factor_multivariate");
329 }
330}
331
337
338}
一元多项式模板类
std::vector< CoeffType > coeffs
系数数组,coeffs[i] 为 x^i 的系数
static Result failure(CasErrc code, std::string message, std::string operation={})
static Result success(T value)
static MultiPoly embed_univariate_factor(const Polynomial< Rational > &factor, const std::vector< std::string > &variables, const std::string &main_variable)
static MultiFactorCheckedResult factor_common_monomial(const MultiPoly &poly, const Monomial &common_monomial, const MultiPoly &quotient, ComputationContext &context)
static MultiFactorCheckedResult factor_multivariate_impl(const MultiPoly &poly, ComputationContext &context)
static MultiFactorCheckedResult factor_difference_of_squares(const MultiPoly &poly, const std::pair< MultiPoly, MultiPoly > &difference, ComputationContext &context)
static MultiFactorCheckedResult factor_binomial_power(const MultiPoly &poly, const MultiPoly &primitive, const std::string &left_variable, const std::string &right_variable, ComputationContext &context)
static MultiFactorCheckedResult factor_embedded_univariate(const MultiPoly &poly, const MultiPoly &primitive, const std::string &main_variable, ComputationContext &context)
std::pair< Monomial, MultiPoly > extract_common_monomial(const MultiPoly &poly)
提取公因子单项式
Result< std::optional< MultiFactorResult > > factor_homogeneous_bivariate(const MultiPoly &poly, ComputationContext &context)
齐次二元多项式分解
std::optional< std::tuple< std::string, std::string, int > > detect_binomial_power(const MultiPoly &poly)
检测二项式幂模式 xⁿ - yⁿ
std::optional< std::pair< MultiPoly, MultiPoly > > detect_difference_of_squares(const MultiPoly &poly)
检测差平方模式 a^2 - b^2
MultiFactorCheckedResult assemble_checked_factorization(const MultiPoly &original, const std::vector< MultiPoly > &factors, const std::vector< int > &multiplicities, Completeness completeness, std::string reason)
std::optional< MultiFactorCheckedResult > factor_evaluated_linear(const MultiPoly &original, const MultiPoly &primitive, const std::string &main_variable, ComputationContext &context)
static Result< void > append_primitive_factor(MultiFactorResult &result, const MultiPoly &raw, int multiplicity)
Result< MathResult< MultiFactorResult > > MultiFactorCheckedResult
const std::string & variable
std::vector< int > Monomial
单项式类型,以整数向量表示各变量的指数
const std::vector< Polynomial< BigInt > > const BigInt ComputationContext & context
ExprResult sub(const ExprPtr &lhs, const ExprPtr &rhs, ComputationContext &context)
std::vector< MultiPoly > factors
精确因子列表(各因子本原)
MultiFactorCheckedResult factor_multivariate_checked(const MultiPoly &poly, ComputationContext &context)
UnivariateFactorResult factor_univariate_bridge_checked(const Polynomial< Rational > &polynomial, ComputationContext &context)
const ExprPtr & exponent
const ExprPtr & right
Rational constant
数值常数因子
std::vector< int > multiplicities
各因子的重数