9#include <gtest/gtest.h>
25concept HasSPoly =
requires(
const MP &f,
const MP &g)
27 { MP::s_poly(f, g) } -> std::same_as<MP>;
33 { MP::groebner_basis(
gens) } -> std::same_as<Array<MP>>;
39 { MP::ideal_member(f,
gens) } -> std::same_as<bool>;
45 { MP::radical_member(f,
gens) } -> std::same_as<bool>;
58 for (
size_t i = 0; i <
basis.size(); ++i)
59 for (
size_t j = i + 1; j <
basis.size(); ++j)
62 auto [q,
r] = s.divmod(
basis);
65 <<
"Non-zero S-polynomial remainder for pair (" << i <<
", " << j <<
")";
72 for (
size_t i = 0; i <
basis.size(); ++i)
75 for (
size_t j = 0; j <
basis.size(); ++j)
85 <<
"Basis element " << i <<
" is still reducible by the rest of the basis";
739 std::ostringstream
oss;
908 {
Idx{1000, 0, 0}, 1.0},
909 {
Idx{0, 750, 1}, 2.0},
918 const double value = p.eval(pt);
1184 for (
size_t i = 0; i < 6; ++i)
1187 data(i) = {
Array<double>{x}, x * x * x + 0.5 * std::sin(i)};
1361 for (
size_t i = 0; i < 2; ++i)
1362 for (
size_t j = 0; j < 2; ++j)
1616 std::string json = f.
to_json();
1625 std::string json = z.
to_json();
1641 std::ostringstream
oss;
1644 std::istringstream
iss(
oss.str());
1653 {
Idx{1, 0, 0}, 1.0},
1654 {
Idx{0, 1, 0}, 2.0},
1655 {
Idx{0, 0, 1}, 3.0},
1658 std::ostringstream
oss;
1661 std::istringstream
iss(
oss.str());
1969 gens(0) = x * x -
y;
1982 auto x = LexPoly::variable(2, 0);
1983 auto y = LexPoly::variable(2, 1);
1986 gens(0) = x * x -
y;
1995 for (
size_t i = 0; i <
basis.size(); ++i)
1998 if ((
basis(i) - (x -
y *
y)).is_zero())
2014 auto x = LexPoly::variable(3, 0);
2015 auto y = LexPoly::variable(3, 1);
2016 auto z = LexPoly::variable(3, 2);
2034 std::mt19937
rng(20260317u);
2035 std::uniform_int_distribution<int>
coeff_dist(-2, 2);
2036 std::uniform_int_distribution<int>
keep_dist(0, 1);
2050 for (
size_t g = 0; g <
gens.size(); ++g)
2068 while (p.is_zero()
or p.degree() == 0);
2070 gens(g) = std::move(p);
2075 for (
size_t g = 0; g <
gens.size(); ++g)
2077 <<
"Generator " << g <<
" did not reduce to zero in trial " <<
trial;
2215 r1.for_each_term([&](
const Idx& idx,
double c) {
2249 for (
size_t i = 0; i <
basis.size(); ++i)
2262 for (
size_t i = 0; i <
basis.size(); ++i)
2273 gens(0) = 2.0 * x +
y;
2279 for (
size_t i = 0; i <
basis.size(); ++i)
2291 auto x = LexPoly::variable(3, 0);
2292 auto y = LexPoly::variable(3, 1);
2293 auto z = LexPoly::variable(3, 2);
2309 for (
size_t i = 0; i <
expected.size(); ++i)
2312 for (
size_t i = 0; i <
basis.size(); ++i)
2320 auto x = LexPoly::variable(4, 0);
2321 auto y = LexPoly::variable(4, 1);
2322 auto z = LexPoly::variable(4, 2);
2323 auto w = LexPoly::variable(4, 3);
2341 for (
size_t i = 0; i <
expected.size(); ++i)
2344 for (
size_t i = 0; i <
basis.size(); ++i)
2352 auto x = LexPoly::variable(5, 0);
2353 auto y = LexPoly::variable(5, 1);
2354 auto z = LexPoly::variable(5, 2);
2355 auto w = LexPoly::variable(5, 3);
2356 auto u = LexPoly::variable(5, 4);
2380 for (
size_t i = 0; i <
expected.size(); ++i)
2383 for (
size_t i = 0; i <
basis.size(); ++i)
3040 for (
auto it = result.get_it(); it.has_curr(); it.next_ne())
3066 for (
auto it = result.get_it(); it.has_curr(); it.next_ne())
3073 for (
auto it = result.get_it(); it.has_curr(); it.next_ne())
3106 for (
auto it =
factors.get_it(); it.has_curr(); it.next_ne())
3138 for (
auto it =
factors.get_it(); it.has_curr(); it.next_ne())
3140 const auto &
ft = it.get_curr();
3141 for (
size_t m = 0;
m <
ft.multiplicity; ++
m)
3146 for (
long long v = -3; v <= 3; ++v)
3150 <<
"Mismatch at x = " << v;
3163 for (
auto it =
factors.get_it(); it.has_curr(); it.next_ne())
3165 const auto &
ft = it.get_curr();
3167 for (
size_t m = 0;
m <
ft.multiplicity; ++
m)
3185 const auto &
ft = it.get_curr();
3202 for (
auto it =
factors.get_it(); it.has_curr(); it.next_ne())
3204 const auto &
ft = it.get_curr();
3206 if (
ft.multiplicity == 1
and ft.factor.is_constant()
and ft.factor.leading_coeff() == 6LL)
3208 for (
size_t m = 0;
m <
ft.multiplicity; ++
m)
3227 for (
auto it =
factors.get_it(); it.has_curr(); it.next_ne())
3229 const auto &
ft = it.get_curr();
3231 if (
ft.multiplicity == 1
and ft.factor.is_constant()
and ft.factor.leading_coeff() == -1LL)
3233 for (
size_t m = 0;
m <
ft.multiplicity; ++
m)
3255 for (
auto it =
factors.get_it(); it.has_curr(); it.next_ne())
3257 const auto &
ft = it.get_curr();
3258 for (
size_t m = 0;
m <
ft.multiplicity; ++
m)
3262 for (
long long v = -2; v <= 5; ++v)
3266 <<
"Mismatch at x = " << v;
3297 for (
auto it =
factors.get_it(); it.has_curr(); it.next_ne())
3299 const auto &
ft = it.get_curr();
3300 if (
ft.multiplicity == 1
and ft.factor.is_constant()
and ft.factor.leading_coeff() == 6LL)
3302 for (
size_t m = 0;
m <
ft.multiplicity; ++
m)
3320 for (
auto it =
factors.get_it(); it.has_curr(); it.next_ne())
3322 const auto &
ft = it.get_curr();
3323 if (
ft.multiplicity == 1
and ft.factor.is_constant()
and ft.factor.leading_coeff() == -1LL)
3325 for (
size_t m = 0;
m <
ft.multiplicity; ++
m)
3346 for (
auto it =
factors.get_it(); it.has_curr(); it.next_ne())
3348 const auto &
ft = it.get_curr();
3350 if (
ft.multiplicity == 1
and (
ft.factor - (x -
y)).is_zero())
3352 if (
ft.multiplicity == 1
and (
ft.factor - (x +
y)).is_zero())
3354 for (
size_t m = 0;
m <
ft.multiplicity; ++
m)
3375 const auto &
ft = it.get_curr();
3398 for (
auto it =
factors.get_it(); it.has_curr(); it.next_ne())
3400 const auto &
ft = it.get_curr();
3402 if (
ft.multiplicity == 1
and (
ft.factor - f1).is_zero())
3404 if (
ft.multiplicity == 1
and (
ft.factor - f2).is_zero())
3406 for (
size_t m = 0;
m <
ft.multiplicity; ++
m)
3415 for (
long long xv = -2;
xv <= 2; ++
xv)
3416 for (
long long yv = -2;
yv <= 2; ++
yv)
3417 for (
long long zv = -2;
zv <= 2; ++
zv)
3424 <<
"Mismatch at (" <<
xv <<
", " <<
yv <<
", " <<
zv <<
")";
3443 for (
auto it =
factors.get_it(); it.has_curr(); it.next_ne())
3445 const auto &
ft = it.get_curr();
3447 if (
ft.multiplicity == 1
and (
ft.factor - f1).is_zero())
3449 if (
ft.multiplicity == 1
and (
ft.factor - f2).is_zero())
3451 for (
size_t m = 0;
m <
ft.multiplicity; ++
m)
3476 for (
auto it =
factors.get_it(); it.has_curr(); it.next_ne())
3478 const auto &
ft = it.get_curr();
3480 if (
ft.multiplicity == 1
and (
ft.factor - f1).is_zero())
3482 if (
ft.multiplicity == 1
and (
ft.factor - f2).is_zero())
3484 for (
size_t m = 0;
m <
ft.multiplicity; ++
m)
3509 for (
auto it =
factors.get_it(); it.has_curr(); it.next_ne())
3511 const auto &
ft = it.get_curr();
3513 if (
ft.multiplicity == 1
and (
ft.factor - f1).is_zero())
3515 if (
ft.multiplicity == 1
and (
ft.factor - f2).is_zero())
3517 for (
size_t m = 0;
m <
ft.multiplicity; ++
m)
3543 for (
auto it =
factors.get_it(); it.has_curr(); it.next_ne())
3545 const auto &
ft = it.get_curr();
3547 if (
ft.multiplicity == 1
and (
ft.factor - f1).is_zero())
3549 if (
ft.multiplicity == 1
and (
ft.factor - f2).is_zero())
3551 for (
size_t m = 0;
m <
ft.multiplicity; ++
m)
3576 for (
auto it =
factors.get_it(); it.has_curr(); it.next_ne())
3578 const auto &
ft = it.get_curr();
3580 if (
ft.multiplicity == 1
and (
ft.factor - f1).is_zero())
3582 if (
ft.multiplicity == 1
and (
ft.factor - f2).is_zero())
3584 for (
size_t m = 0;
m <
ft.multiplicity; ++
m)
3610 for (
auto it =
factors.get_it(); it.has_curr(); it.next_ne())
3612 const auto &
ft = it.get_curr();
3614 if (
ft.multiplicity == 1
and (
ft.factor - f1).is_zero())
3616 if (
ft.multiplicity == 1
and (
ft.factor - f2).is_zero())
3618 for (
size_t m = 0;
m <
ft.multiplicity; ++
m)
3643 for (
auto it =
factors.get_it(); it.has_curr(); it.next_ne())
3645 const auto &
ft = it.get_curr();
3647 if (
ft.multiplicity == 1
and (
ft.factor - f1).is_zero())
3649 if (
ft.multiplicity == 1
and (
ft.factor - f2).is_zero())
3651 for (
size_t m = 0;
m <
ft.multiplicity; ++
m)
3673 for (
auto it =
factors.get_it(); it.has_curr(); it.next_ne())
3679 for (
auto it =
factors.get_it(); it.has_curr(); it.next_ne())
3681 const auto &
ft = it.get_curr();
3682 for (
size_t m = 0;
m <
ft.multiplicity; ++
m)
3686 for (
long long xv = -2;
xv <= 2; ++
xv)
3687 for (
long long yv = -2;
yv <= 2; ++
yv)
constexpr size_t size() const noexcept
Return the number of elements stored in the stack.
T & append(const T &data)
Append a copy of data
Sparse multivariate polynomial.
static bool radical_member(const Gen_MultiPolynomial &f, const Array< Gen_MultiPolynomial > &gens)
Test membership in radical of ideal: f ∈ √I.
static Array< Gen_MultiPolynomial > reduced_groebner_basis(const Array< Gen_MultiPolynomial > &generators)
Reduced Gröbner basis (minimized and normalized).
static Gen_MultiPolynomial fit(const Array< std::pair< Array< Coefficient >, Coefficient > > &data, const size_t nvars, const Array< Array< size_t > > &basis)
Basic least-squares polynomial fitting.
Gen_MultiPolynomial primitive_part() const
Primitive part: polynomial divided by its content.
Gen_MultiPolynomial reduce_modulo(const Array< Gen_MultiPolynomial > &divisors) const
Polynomial reduction modulo an ideal (one-liner).
Gen_MultiPolynomial partial(size_t var, size_t n=1) const
Partial derivative with respect to a variable.
static Gen_MultiPolynomial fit_ridge(const Array< std::pair< Array< Coefficient >, Coefficient > > &data, size_t nvars, const Array< Array< size_t > > &basis, Coefficient *lambda_used=nullptr, double *gcv_score=nullptr)
Regularized least-squares fitting with automatic GCV-based lambda selection.
std::string to_json() const
Serialize polynomial to JSON string.
static bool contains_ideal(const Array< Gen_MultiPolynomial > &I_gens, const Array< Gen_MultiPolynomial > &J_gens)
Test whether ideal I contains ideal J: I ⊇ J.
DynList< FactorTerm > factorize() const
Main multivariate factorization over the integers.
bool is_constant() const noexcept
True if constant or zero (total degree 0).
static Gen_MultiPolynomial s_poly(const Gen_MultiPolynomial &f, const Gen_MultiPolynomial &g)
S-polynomial (Sylvester polynomial) of two polynomials.
Array< Coefficient > eval_batch(const Array< Array< Coefficient > > &pts) const
Evaluate polynomial at multiple points (with parallelism support).
void to_binary(std::ostream &out) const
Serialize polynomial to binary stream.
std::string to_str(const DynList< std::string > &names=DynList< std::string >()) const
Human-readable string.
void for_each_term(Op &&op) const
Visit every non-zero term in ascending monomial order.
Array< Coefficient > eval_gradient(const Array< Coefficient > &pt) const
Evaluate gradient at a point.
std::pair< Array< size_t >, Coefficient > leading_term() const
Leading term (largest monomial in the ordering).
static Gen_MultiPolynomial interpolate(const Array< Array< Coefficient > > &grid, const Array< Coefficient > &values, size_t nvars)
Multivariate interpolation via Newton divided differences (Chung-Yao).
static Gen_MultiPolynomial monomial(size_t nvars, const Array< size_t > &idx, const Coefficient &c=Coefficient(1))
A single monomial .
size_t num_terms() const noexcept
Number of non-zero terms.
bool is_zero() const noexcept
True if this is the zero polynomial.
Coefficient content() const
Content of a multivariate polynomial: GCD of all coefficients.
static Gen_MultiPolynomial fit_parallel(const Array< std::pair< Array< Coefficient >, Coefficient > > &data, size_t nvars, const Array< Array< size_t > > &basis)
Parallel least-squares fitting.
Array< Array< Coefficient > > eval_hessian(const Array< Coefficient > &pt) const
Evaluate Hessian at a point.
static Array< Gen_MultiPolynomial > ideal_power(const Array< Gen_MultiPolynomial > &gens, size_t n)
Power of an ideal: I^n = I · I · ... · I (n times).
Gen_MultiPolynomial promote(size_t new_nv) const
Promote to a polynomial with more variables.
Array< Gen_MultiPolynomial > gradient() const
Gradient vector: array of all first-order partial derivatives.
static Gen_MultiPolynomial from_json(const std::string &s)
Deserialize from JSON.
Gen_Polynomial< Coefficient > homomorphic_eval(size_t keep_var, const Array< Coefficient > &eval_pts) const
Homomorphic evaluation: reduce to univariate by substitution.
static DynList< FactorTerm > factor_recombination(Gen_MultiPolynomial f, const Array< Gen_MultiPolynomial > &candidates)
Factor recombination: find true factors from lifted candidates.
static Gen_MultiPolynomial variable(size_t nvars, const size_t var)
The polynomial (a single variable).
static Array< Gen_MultiPolynomial > groebner_basis(const Array< Gen_MultiPolynomial > &generators)
Gröbner basis computation via Buchberger's algorithm.
void add_to_coeff(const Array< size_t > &idx, const Coefficient &delta)
Add delta to the coefficient at idx.
static Gen_MultiPolynomial from_binary(std::istream &in)
Deserialize polynomial from binary stream.
Coefficient coeff_at(const Array< size_t > &idx) const
Read coefficient at a multi-index (0 if absent).
size_t num_vars() const noexcept
Number of variables.
static Array< Gen_MultiPolynomial > ideal_sum(const Array< Gen_MultiPolynomial > &a, const Array< Gen_MultiPolynomial > &b)
Sum of two ideals: I + J = ⟨generators(I) ∪ generators(J)⟩.
Gen_MultiPolynomial pow(size_t n) const
Exponentiation by repeated squaring.
Array< Array< Gen_MultiPolynomial > > hessian() const
Hessian matrix: all second-order partial derivatives.
static bool ideal_member(const Gen_MultiPolynomial &f, const Array< Gen_MultiPolynomial > &generators)
Test membership in an ideal via Gröbner basis.
std::pair< Array< Gen_MultiPolynomial >, Gen_MultiPolynomial > divmod(const Array< Gen_MultiPolynomial > &divisors) const
Multivariate division with remainder (Buchberger algorithm).
Coefficient eval(const Array< Coefficient > &pt) const
Evaluate at a point.
static Array< Gen_MultiPolynomial > ideal_product(const Array< Gen_MultiPolynomial > &a, const Array< Gen_MultiPolynomial > &b)
Product of two ideals: I · J = ⟨a_i · b_j : a_i ∈ I, b_j ∈ J⟩.
size_t degree() const noexcept
Total degree (maximum sum of exponents over all terms).
DynList< std::pair< Array< size_t >, Coefficient > > terms() const
All terms as a list (ascending order).
static Gen_MultiPolynomial fit_weighted(const Array< std::pair< Array< Coefficient >, Coefficient > > &data, size_t nvars, const Array< Array< size_t > > &basis, const Array< Coefficient > &weights)
Weighted least-squares polynomial fitting.
static bool ideals_equal(const Array< Gen_MultiPolynomial > &I_gens, const Array< Gen_MultiPolynomial > &J_gens)
Test equality of two ideals: I = J.
Univariate polynomial over a generic coefficient ring.
Coefficient get_coeff(size_t exp) const noexcept
Coefficient accessor (read-only at exponent).
constexpr size_t size() const noexcept
Returns the number of entries in the table.
__gmp_expr< typename __gmp_resolve_expr< T, V >::value_type, __gmp_binary_expr< __gmp_expr< T, U >, __gmp_expr< V, W >, __gmp_pow_function > > pow(const __gmp_expr< T, U > &expr1, const __gmp_expr< V, W > &expr2)
Gen_MultiPolynomial< long long, Grevlex_Order > IntMPoly
static void expect_buchberger_criterion(const Array< MP > &basis)
static void expect_autoreduced_basis(const Array< MP > &basis)
Main namespace for Aleph-w library functions.
and
Check uniqueness with explicit hash + equality functors.
size_t size(Node *root) noexcept
Gen_MultiPolynomial< double, Grevlex_Order > MultiPolynomial
Multivariate polynomial with double coefficients, grevlex.
Divide_Conquer_DP_Result< Cost > divide_and_conquer_partition_dp(const size_t groups, const size_t n, Transition_Cost_Fn transition_cost, const Cost inf=dp_optimization_detail::default_inf< Cost >())
Optimize partition DP using divide-and-conquer optimization.
PolyFitAnalysis< C > analyze_fit(const Gen_MultiPolynomial< C, M > &poly, const Array< std::pair< Array< C >, C > > &data)
Compute residual analysis for a polynomial fit.
T product(const Container &container, const T &init=T{1})
Compute product of all elements.
bool diff(const C1 &c1, const C2 &c2, Eq e=Eq())
Check if two containers differ.
static long & df(typename GT::Node *p)
Internal helper: DFS discovery time stored in NODE_COUNTER(p).
Itor::difference_type count(const Itor &beg, const Itor &end, const T &value)
Count elements equal to a value.
Structure holding residual analysis for polynomial fits.
double rmse
Root mean squared error.
double rss
Residual sum of squares.
double ess
Explained sum of squares.
Array< C > residuals
Per-point residuals.
double r_squared
Coefficient of determination (0–1)
double mean_y
Mean of y values.
double tss
Total sum of squares.
FooMap m(5, fst_unit_pair_hash, snd_unit_pair_hash)
Sparse multivariate polynomial over an arbitrary coefficient ring.