13 const MultiPoly& raw,
int multiplicity) {
14 if (multiplicity <= 0) {
16 "因子重数必须为正",
"factor_multivariate");
19 MultiPoly factor = raw.make_primitive();
20 if (!factor.terms().empty() && factor.terms()[0].second < Rational(0)) {
21 factor = factor * Rational(-1);
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));
28 const auto index =
static_cast<size_t>(existing - result.
factors.begin());
35 const MultiPoly& original,
36 const std::vector<MultiPoly>& raw_factors,
37 const std::vector<int>& raw_multiplicities,
41 constexpr const char* operation =
"factor_multivariate";
42 if (original.is_zero()) {
43 if (!raw_factors.empty()) {
50 completeness, std::move(reason)});
54 for (
size_t i = 0; i < raw_factors.size(); ++i) {
55 const int multiplicity = i < raw_multiplicities.size() ? raw_multiplicities[i] : 1;
59 MultiPoly product(Rational(1), original.variables());
60 for (
size_t i = 0; i < result.
factors.size(); ++i) {
62 product = product * result.
factors[i];
65 MultiPoly quotient = original.exact_div(product);
66 if (!quotient.is_constant() || quotient.terms().empty()) {
69 "因子乘积与输入只差常数的不变量失效", operation);
71 result.
constant = quotient.terms()[0].second;
72 if (product * result.
constant != original) {
78 std::move(result), completeness, std::move(reason)});
93 const std::vector<std::string>& variables,
94 const std::string& main_variable)
96 size_t main_index = variables.size();
97 for (
size_t i = 0; i < variables.size(); ++i) {
98 if (variables[i] == main_variable) {
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]);
110 return MultiPoly(std::move(terms), variables);
117 const MultiPoly& poly,
const Monomial& common_monomial,
119 const auto& variables = poly.variables();
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);
128 factors.emplace_back(
129 std::vector<MultiPoly::Term>{{monomial, Rational(1)}},
131 multiplicities.push_back(common_monomial[i]);
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));
146 const MultiPoly& poly,
const std::pair<MultiPoly, MultiPoly>& difference,
148 std::vector<MultiPoly> factors;
149 std::vector<int> multiplicities;
152 for (MultiPoly candidate :
153 {difference.first + difference.second,
154 difference.first - difference.second}) {
157 auto sub_value = std::move(
sub.
value());
160 if (reason.empty()) reason = sub_value.reason;
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());
171 poly, factors, multiplicities, completeness, std::move(reason));
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;
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;
190 std::vector<MultiPoly::Term>{
191 {left_monomial, Rational(1)},
192 {right_monomial, Rational(-1)}},
194 MultiPoly remaining = primitive.exact_div(linear);
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));
212 const MultiPoly& poly,
const MultiPoly& primitive,
214 const auto& variables = poly.variables();
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) {
226 factor, variables, main_variable));
229 poly, factors, std::vector<int>(factors.size(), 1),
230 factor_value.completeness, std::move(factor_value.reason));
234 const MultiPoly& poly,
237 constexpr const char* operation =
"factor_multivariate";
238 auto recursion =
context.enter_recursion(operation);
242 if (poly.is_zero()) {
246 if (poly.is_constant()) {
250 const auto& variables = poly.variables();
251 if (variables.empty()) {
254 "非常数多项式缺少变量表", operation);
257 std::string main_variable = variables.front();
258 for (
const auto&
variable : variables) {
259 if (poly.degree(
variable) > poly.degree(main_variable)) {
263 if (poly.total_degree() <= 1) {
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) {
276 MultiPoly primitive = poly.make_primitive();
285 if (primitive.is_univariate()) {
289 if (evaluated)
return std::move(*evaluated);
295 if (homogeneous.value()) {
296 auto& result = *homogeneous.value();
298 poly, result.factors, result.multiplicities,
304 "当前受检算法无法证明该多项式不可约");
310 const MultiPoly& poly,
314 auto factored = factor_multivariate_impl(poly,
context);
318 std::move(factored.value().reason));
321 }
catch (
const std::bad_alloc&) {
324 "factor_multivariate");
325 }
catch (
const std::exception& error) {
328 "factor_multivariate");
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 "ient, 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)
std::vector< int > multiplicities
各因子的重数
ComputationContext & context