13 const MultiPoly& poly,
15 const std::map<std::string, Rational>& eval_points,
18 if (univariate_factors.empty()) {
return false; }
22 for (
const auto& factor : univariate_factors) {
23 if (factor.variable_name !=
main_var || factor.is_zero()) {
return false; }
24 product = product * factor;
26 auto [
unit, remainder] = specialized.
div_mod(product);
27 if (!remainder.is_zero() ||
unit.is_zero() ||
unit.degree() != 0) {
return false; }
28 if (!(product *
unit == specialized)) {
return false; }
29 univariate_factors[0] = univariate_factors[0] *
unit;
43 const LinearSamples& input, std::vector<std::vector<Rational>>& samples) {
48 MultiPoly evaluated = input.
primitive.eval(sample);
55 std::vector<Rational> constants;
56 for (
const auto& factor : factored.value().value) {
58 constants.push_back(factor.make_monic().coeffs[0]);
60 samples.push_back(std::move(constants));
67 const std::vector<std::vector<Rational>>&
samples;
74 std::vector<MultiPoly::Term> terms;
75 Monomial main_monomial(variables.size(), 0);
76 const size_t main_index =
static_cast<size_t>(std::find(
78 main_monomial[main_index] = 1;
79 terms.emplace_back(main_monomial, Rational(1));
80 Monomial constant_monomial(variables.size(), 0);
82 if (!constant.is_zero()) terms.emplace_back(constant_monomial, constant);
83 for (
size_t variable_index = 0; variable_index < search.
input.
auxiliary.size(); ++variable_index) {
84 Rational coefficient = search.
samples[variable_index]
85 [search.
assignments[variable_index][factor_index]] - constant;
86 if (coefficient.is_zero()) {
continue; }
87 Monomial monomial(variables.size(), 0);
88 const size_t index =
static_cast<size_t>(std::find(
89 variables.begin(), variables.end(), search.
input.
auxiliary[variable_index]) - variables.begin());
91 terms.emplace_back(std::move(monomial), coefficient);
93 return MultiPoly(std::move(terms), variables);
99 std::vector<MultiPoly> candidates;
103 MultiPoly product(Rational(1), search.
input.
primitive.variables());
104 for (
const auto& candidate : candidates) product = product * candidate;
108 }
catch (
const std::runtime_error&) {
111 if (
unit.is_zero() || !
unit.is_constant() ||
120 std::sort(permutation.begin(), permutation.end());
123 if (!found || found.value()) {
return found; }
124 }
while (std::next_permutation(permutation.begin(), permutation.end()));
130 std::vector<std::vector<Rational>> samples;
133 if (!collected.value()) {
return std::nullopt; }
135 std::vector<std::vector<size_t>>(input.
auxiliary.size(),
138 for (
size_t i = 0; i < assignment.size(); ++i) assignment[i] = i;
142 if (!found.value()) {
return std::nullopt; }
148 const MultiPoly& poly,
const MultiPoly& primitive,
149 const std::string& main_variable,
const std::vector<std::string>& auxiliary_variables,
150 const std::map<std::string, Rational>& zero_evaluation,
152 constexpr const char* operation =
"factor_multivariate";
153 const auto& variables = primitive.variables();
154 auto hensel_step =
context.consume_steps(
156 std::max(1, primitive.degree(auxiliary_variables[0]))),
161 std::vector<Polynomial<Rational>> prepared = base_value.value;
163 primitive, main_variable, zero_evaluation, prepared)) {
return std::nullopt; }
165 primitive, prepared, auxiliary_variables[0], Rational(0),
166 primitive.degree(auxiliary_variables[0]));
167 MultiPoly lifted_product(Rational(1), variables);
168 for (
const auto& factor : lifted) {
169 lifted_product = lifted_product * factor;
171 if (lifted.size() > 1 && lifted_product == primitive) {
172 const bool all_linear = std::all_of(lifted.begin(), lifted.end(),
173 [](
const MultiPoly& factor) { return factor.total_degree() == 1; });
175 poly, lifted, std::vector<int>(lifted.size(), 1),
177 all_linear ? std::string{} :
"提升因子的不可约性尚未证明");
183 const MultiPoly& poly,
const MultiPoly& primitive,
185 const auto& variables = primitive.variables();
186 std::vector<std::string> auxiliary_variables;
187 for (
const auto&
variable : variables) {
190 std::map<std::string, Rational> zero_evaluation;
191 for (
const auto&
variable : auxiliary_variables) {
192 zero_evaluation[
variable] = Rational(0);
194 MultiPoly evaluated = primitive.eval(zero_evaluation);
195 if (evaluated.degree(main_variable) != primitive.degree(main_variable)) {
return std::nullopt; }
202 auto base_value = std::move(base_result.value());
203 bool all_linear = base_value.value.size() > 1;
204 for (
const auto& factor : base_value.value) {
205 all_linear = all_linear && factor.degree() == 1;
207 if (!all_linear) {
return std::nullopt; }
208 if (auxiliary_variables.size() == 1) {
210 auxiliary_variables, zero_evaluation, base_value,
context);
211 if (hensel) {
return hensel; }
213 std::vector<Rational> base_constants;
214 for (
const auto& factor : base_value.value) {
215 base_constants.push_back(factor.make_monic().coeffs[0]);
217 LinearSamples input{primitive, main_variable, auxiliary_variables,
218 zero_evaluation, base_constants,
context};
Result< void > consume_steps(std::size_t amount=1, const std::string &operation={})
std::pair< Polynomial, Polynomial > div_mod(const Polynomial &other) const
多项式带余除法
std::string variable_name
变量名
static Result failure(CasErrc code, std::string message, std::string operation={})
static Result success(T value)
static Result< bool > collect_linear_samples(const LinearSamples &input, std::vector< std::vector< Rational > > &samples)
std::vector< MultiPoly > found_factors
const std::vector< std::string > & auxiliary
static MultiPoly linear_assignment_factor(const LinearAssignments &search, size_t factor_index)
std::vector< std::vector< size_t > > assignments
const std::string & main_variable
ComputationContext & context
MultiFactorCheckedResult assemble_checked_factorization(const MultiPoly &original, const std::vector< MultiPoly > &factors, const std::vector< int > &multiplicities, Completeness completeness, std::string reason)
static Result< bool > enumerate_linear_assignments(LinearAssignments &search, size_t index)
std::optional< MultiFactorCheckedResult > factor_evaluated_linear(const MultiPoly &original, const MultiPoly &primitive, const std::string &main_variable, ComputationContext &context)
static Result< bool > verify_linear_assignment(LinearAssignments &search)
static std::optional< MultiFactorCheckedResult > factor_linear_hensel(const MultiPoly &poly, const MultiPoly &primitive, const std::string &main_variable, const std::vector< std::string > &auxiliary_variables, const std::map< std::string, Rational > &zero_evaluation, MathResult< std::vector< Polynomial< Rational > > > &base_value, ComputationContext &context)
const MultiPoly & primitive
const std::vector< std::vector< Rational > > & samples
static std::optional< MultiFactorCheckedResult > factor_linear_assignments(const MultiPoly &original, const LinearSamples &input)
const std::map< std::string, Rational > & zero_evaluation
static bool restore_specialization_unit(const MultiPoly &poly, const std::string &main_var, const std::map< std::string, Rational > &eval_points, std::vector< Polynomial< Rational > > &univariate_factors)
const LinearSamples & input
const std::vector< Rational > & base_constants
const std::string & variable
std::vector< int > Monomial
单项式类型,以整数向量表示各变量的指数
const std::vector< Polynomial< BigInt > > const BigInt ComputationContext & context
UnivariateFactorResult factor_univariate_bridge_checked(const Polynomial< Rational > &polynomial, ComputationContext &context)
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 提升(单变量步)
const std::string & main_var