8#include <M2/math-include.h>
14#define dlopen(x, y) NULL
15#define dlsym(x, y) NULL
16#define dlclose(x) (-1)
77 printf(
"closing library\n");
95 ERROR(
"max number of slps exceeded");
100 ERROR(
"invalid SLP");
111 ERROR(
"different number of constants expected");
125 snprintf(libname, 100,
131 const char* funname =
"slpFN";
132 printf(
"loading slpFN from %s\n", libname);
134 if (res->
handle ==
nullptr)
ERROR(
"can't load library %s", libname);
139 "can't link function %s from library %s", funname, libname);
161template <
class Field>
167template <
class Field>
198 Nterm* prev_f =
nullptr;
201 if (f->
monom[i] == 0)
209 if (prev_f !=
nullptr)
219 f = (prev_f ==
nullptr) ? ff : prev_f->
next;
225template <
class Field>
227 typename Field::element_type c)
231 return static_cast<int>(consts.size()) - 1;
236template <
class Field>
242 std::vector<int> part_pos(n);
244 for (
int i = 0; i < n; i++)
255 prog.push_back(n - 1 - i);
257 prog.push_back(
p - part_pos[i]);
261 if (f !=
nullptr) c++;
262 for (
int i = 0; i < n; i++)
265 if (c == 1 && last_nonzero_part_pos !=
ZERO_CONST)
266 return last_nonzero_part_pos;
275 for (
int i = 0; i < n; i++)
277 prog.push_back(part_pos[i] - cur_p);
284 for (; f !=
nullptr; f = f->
next)
285 for (
int i = 0; i < n - 1; i++) f->
monom[i] -= f->
monom[i + 1];
288template <
class Field>
295 ERROR(
"max number of slps exceeded");
329 static_cast<int>(consts.size());
339 sizeof(
int) * prog.size());
346 res->
nodes[i] = consts[i];
352template <
class Field>
358 ERROR(
"slps unstackable");
386 int* res_end_program =
387 res->
program->array + res->
program->len - slp_num_outputs - num_outputs;
390 memcpy(res_start_program,
393 memcpy(res_end_program, end_program, num_outputs *
sizeof(
int));
394 for (
int *a = res_end_program, i = 0; i < num_outputs; i++, a++)
399 memcpy(res_end_program - slp_len, slp_start_program, slp_len *
sizeof(
int));
400 for (
int *a = res_end_program - slp_len, i = 0;
405 memcpy(res_end_program + num_outputs,
406 slp_start_program + slp_len,
407 slp_num_outputs *
sizeof(
int));
408 for (
int *a = res_end_program + num_outputs, i = 0; i < slp_num_outputs;
433template <
class Field>
449template <
class Field>
461 int n_summands = prog[(++i)++];
462 std::vector<int> part_pos(n_summands);
465 for (
int j = 0; j < n_summands; j++)
471 last_non_zero = part_pos[j];
475 if (c == 1)
return last_non_zero;
480 for (
int j = 0; j < n_summands; j++)
483 prog.push_back(part_pos[j] -
490 int a = prog[(++i)++];
520 prog.push_back(da - cur_p);
535 int cur_p = num_operations++;
536 node_index.push_back(prog.size());
545 ERROR(
"input node not expected");
554 prog.push_back(db - cur_p);
564 int is_part1_created = (da !=
ONE_CONST);
565 if (is_part1_created)
567 int cur_p = num_operations++;
568 node_index.push_back(prog.size());
570 prog.push_back(da - cur_p);
577 int is_part2_created = (db !=
ONE_CONST);
578 if (is_part2_created)
580 int cur_p = num_operations++;
581 node_index.push_back(prog.size());
583 prog.push_back(db - cur_p);
589 int cur_p = num_operations++;
590 node_index.push_back(prog.size());
593 if (is_part1_created)
594 prog.push_back(part1 - cur_p);
596 prog.push_back((b < 0) ? b + n - cur_p : b);
597 if (is_part2_created)
598 prog.push_back(part2 - cur_p);
600 prog.push_back((a < 0) ? a + n - cur_p : a);
605 ERROR(
"unknown SLP operation");
606 printf(
"i = %d, a[i] = %d\n", i, prog[i]);
611template <
class Field>
621 ERROR(
"1-row slp expected");
640 i <
program->len - num_outputs - 1 ;
642 prog.push_back(
program->array[i]);
645 std::vector<int> out_pos(res->
rows_out *
648 for (
int j = 0; j < num_outputs; j++)
665 for (
int j = 0; j < num_outputs; j++)
667 int t = out_pos[i * res->
cols_out + j];
675 sizeof(
int) * prog.size());
691 slpHxH = res->
copy();
693 for (
int j = 0; j < num_outputs; j++, c++)
698 slpHxtH = res->
copy();
702 memcpy(slpHxtH->
program->array,
704 sizeof(
int) * res->
program->len);
706 for (
int j = 0; j < num_outputs; j++, c++)
712template <
typename Field>
718 int out_entries_shift = 0;
758 int n_summands =
program->array[i + 1];
764 for (
int j = 1; j < n_summands; j++)
776 ERROR(
"unknown SLP operation");
780 out_entries_shift = i + 1;
798 for (
int j = 0; j <
cols_out; j++, c++)
804template <
class Field>
808 int out_entries_shift = 0;
813 ERROR(
"different number of inputs expected");
840 int n_summands =
program->array[i + 1];
846 for (
int j = 1; j < n_summands; j++)
858 ERROR(
"unknown SLP operation");
862 out_entries_shift = i + 1;
886 for (
int j = 0; j <
cols_out; j++, c++)
913template <
class Field>
932 int n_summands = a[(++i)++];
933 for (
int j = 0; j < n_summands; j++)
942 ERROR(
"unknown SLP operation");
943 printf(
"i = %d, a[i] = %d\n", i, a[i]);
949template <
class Field>
953 <<
" times, total evaluation time = " << (
eval_time / CLOCKS_PER_SEC) <<
"."
957template <
class Field>
964 o <<
"(SLP is precompiled) " <<
newline;
980 nodes[cur_node].snprint(
s, 100);
984 o <<
"INPUT (count = " <<
num_inputs <<
") nodes:\n";
985 for (i = 0; i <
num_inputs; i++, cur_node++) o << cur_node <<
" ";
992 o <<
"SLPs: " <<
program->array[6] <<
"," <<
program->array[7] <<
","
998 o << cur_node <<
" => ";
1002 o <<
"copy " <<
program->array[(++i)++];
1007 int n_summands =
program->array[i + 1];
1008 for (j = 0; j < n_summands; j++)
1009 o <<
" " <<
program->array[i + j + 2];
1010 i += n_summands + 2;
1014 o <<
"product " <<
program->array[i + 1] <<
" "
1019 o <<
"BLA i=" << i++;
1023 int out_shift = i + 1;
1178 for (i = 0; i < size; i++)
1179 for (j = 0; j < size; j++)
1180 *(At + i * size + j) = *(A + j * size + i);
1181 double* copyA = (
double*)At;
1183 double* copyb = (
double*)
x;
1193 zgesv_(&size, &bsize, copyA, &size, permutation, copyb, &size, &info);
1202 ERROR(
"according to zgesv, matrix is singular");
1207 ERROR(
"argument passed to zgesv had an illegal value");
1231 double* copyA = (
double*)A;
1233 double* copyb = (
double*)
x;
1244 zgesv_(&size, &bsize, copyA, &size, permutation, copyb, &size, &info);
1258 ERROR(
"argument passed to zgesv had an illegal value");
1276 int min = (rows <= cols) ? rows : cols;
1280 ERROR(
"expected a matrix with positive dimensions");
1284 int max = (rows >= cols) ? rows : cols;
1285 int wsize = 4 * min + 2 *
max;
1289 double* copyA = (
double*)A;
1312 ERROR(
"argument passed to zgesvd had an illegal value");
1317 ERROR(
"zgesvd did not converge");
1322 cond = sigma[0] / sigma[size - 1];
1346 int min = (rows <= cols) ? rows : cols;
1350 ERROR(
"expected a matrix with positive dimensions");
1354 int max = (rows >= cols) ? rows : cols;
1355 int wsize = 4 * min + 2 *
max;
1359 double* copyA = (
double*)A;
1382 ERROR(
"argument passed to zgesvd had an illegal value");
1387 ERROR(
"zgesvd did not converge");
1392 if (sigma[size - 1] == 0)
1394 ERROR(
"invertible matrix expected");
1397 norm = 1 / sigma[size - 1];
1440 if (
S->n_rows() != 1 ||
T->n_rows() != 1)
1442 ERROR(
"1-row matrices expected");
1446 const PolyRing* R =
p->homotopy_R =
S->get_ring()->cast_to_PolyRing();
1449 ERROR(
"polynomial ring expected");
1457 ERROR(
"complex coefficients expected");
1460 p->productST = mpfr_get_d(
productST, MPFR_RNDN);
1465 p->bigT = acos(
p->productST);
1467 int n =
S->n_cols() + 1;
1468 p->maxDegreeTo3halves = 0;
1470 p->DMforPN[n - 1] = 1;
1473 for (
int i = 0; i < n - 1; i++)
1476 if (d >
p->maxDegreeTo3halves)
p->maxDegreeTo3halves = d;
1477 p->DMforPN[i] = 1 / sqrt(d);
1479 if (
p->slpS ==
nullptr)
1489 p->slpSx =
p->slpS->jacobian(
false,
p->slpHxH ,
true,
p->slpSxS);
1490 p->maxDegreeTo3halves =
p->maxDegreeTo3halves * sqrt(
p->maxDegreeTo3halves);
1494 for (
int i = 0; i <
T->n_cols(); i++)
1497 if (
p->slpT ==
nullptr)
1507 p->slpTx =
p->slpT->jacobian(
false,
p->slpHxH ,
true,
p->slpTxT);
1520 ERROR(
"1-row matrix expected");
1528 ERROR(
"polynomial ring expected");
1535 ERROR(
"complex coefficients expected");
1541 for (
int i = 0; i < HH->
n_cols(); i++)
1544 if (
p->slpH ==
nullptr)
1554 p->slpHxt =
p->slpH->jacobian(
true,
p->slpHxH,
true,
p->slpHxtH);
1565 p->slpHxt =
p->slpHxtH = slp_pred;
1566 p->slpHxH = slp_corr;
1599 PT->
track(start_sols);
1635 int max_corr_steps_refine)
1637 return PT->
refine(sols, tolerance, max_corr_steps_refine);
1642 double the_smallest_number = 1e-13;
1643 double epsilon2 = mpfr_get_d(
epsilon, MPFR_RNDN);
1644 epsilon2 *= epsilon2;
1645 double t_step = mpfr_get_d(
init_dt, MPFR_RNDN);
1646 double dt_min_dbl = mpfr_get_d(
min_dt, MPFR_RNDN);
1650 infinity_threshold2 *= infinity_threshold2;
1662 "epsilon2 = %e, t_step = %lf, dt_min_dbl = %lf, dt_increase_factor_dbl "
1663 "= %lf, dt_decrease_factor_dbl = %lf\n",
1667 dt_increase_factor_dbl,
1668 dt_decrease_factor_dbl);
1696 for (i = 0; i <
n_sols; i++)
1697 for (j = 0; j < n; j++, c++)
1703 for (
int sol_n = 0; sol_n <
n_sols; sol_n++, s_s += n, t_s++)
1707 bool end_zone =
false;
1714 int predictor_successes = 0;
1717 1 - t0->
getreal() > the_smallest_number)
1719 if (1 - t0->
getreal() <= end_zone_factor_dbl + the_smallest_number &&
1737 bool LAPACK_success =
false;
1754 n, LHS, 1, RHS, dx);
1761 RHS = HxtH + n * (n + 1);
1767 n, LHS, 1, RHS, dx);
1784 n, dx1, one_half * (*dt));
1787 xt[n] += one_half * (*dt);
1795 n, LHS, 1, RHS, dx2);
1799 n, dx2, one_half * (*dt));
1812 n, LHS, 1, RHS, dx3);
1827 n, LHS, 1, RHS, dx4);
1847 n, LHS, 1, RHS, dx);
1856 for (j = 0; j < n; j++)
1857 for (i = 0; i < n; i++)
1858 *(LHS + n * i + j) =
1859 *(LHS + n * i + j) *
1872 ERROR(
"unknown predictor");
1880 int n_corr_steps = 0;
1907 predictor_successes = 0;
1908 *dt =
complex(dt_decrease_factor_dbl) * (*dt);
1914 predictor_successes = predictor_successes + 1;
1917 if (is_successful &&
1920 predictor_successes = 0;
1921 *dt =
complex(dt_increase_factor_dbl) * (*dt);
1937 if (sol_n % 50 == 0) printf(
"\n");
1980 int max_corr_steps_refine)
1982 double epsilon2 = mpfr_get_d(tolerance, MPFR_RNDN);
1983 epsilon2 *= epsilon2;
1987 ERROR(
"complex coordinates expected");
1992 ERROR(
"incorrect number of coordinates");
2009 for (i = 0; i <
n_sols; i++)
2010 for (j = 0; j < n; j++, c++)
2014 for (
int sol_n = 0; sol_n <
n_sols; sol_n++, s_s += n)
2020 int n_corr_steps = 0;
2035 while (!is_successful and n_corr_steps < max_corr_steps_refine);
2037 printf(
"max number of corrector steps exceeded for solution %d", sol_n);
2052 for (i = 0; i <
n_sols; i++)
2053 for (j = 0; j < n; j++, c++)
2076 if (solN < 0 || solN >=
n_sols)
return nullptr;
2086 for (
int j = 0; j <
n_coords; j++, c++)
2110 for (
int i = 0; i <
n_sols; i++,
s++)
2113 for (
int j = 0; j <
n_coords; j++, c++)
2130 if (solN < 0 || solN >=
n_sols)
return -1;
2136 if (solN < 0 || solN >=
n_sols)
return -1;
2142 if (solN < 0 || solN >=
n_sols)
return nullptr;
2144 mpfr_init2(
result,
C->get_precision());
2151 if (solN < 0 || solN >=
n_sols)
return nullptr;
2153 mpfr_init2(
result,
C->get_precision());
2160 o <<
"path tracker #" <<
number;
2210 for (i = 0; i < size; i++)
2212 for (j = 0; j < size; j++)
2213 printf(
"(%lf %lf) ",
2214 *(A + 2 * (size * i + j)),
2215 *(A + 2 * (size * i + j) + 1));
int add_constant_get_position(gc_vector< typename Field::element_type > &consts, typename Field::element_type c)
bool cond_number_via_svd(int size, complex *A, double &cond)
void rawSetParametersPT(PathTracker *PT, M2_bool is_projective, gmp_RR init_dt, gmp_RR min_dt, gmp_RR dt_increase_factor, gmp_RR dt_decrease_factor, int num_successes_before_increase, gmp_RR epsilon, int max_corr_steps, gmp_RR end_zone_factor, gmp_RR infinity_threshold, int pred_type)
bool norm_of_inverse_via_svd(int size, complex *A, double &norm)
const Matrix * rawGetSolutionPT(PathTracker *PT, int solN)
int rawGetSolutionStatusPT(PathTracker *PT, int solN)
gmp_RRorNull rawGetSolutionLastTvaluePT(PathTracker *PT, int solN)
bool solve_via_lapack(int size, complex *A, int bsize, complex *b, complex *x)
void print_complex_matrix(int size, const double *A)
void monomials_to_conventional_expvectors(int n, Nterm *f)
int rawGetSolutionStepsPT(PathTracker *PT, int solN)
int degree_ring_elem(const PolyRing *R, ring_elem re)
const Matrix * rawRefinePT(PathTracker *PT, const Matrix *sols, gmp_RR tolerance, int max_corr_steps_refine)
bool solve_via_lapack_without_transposition(int size, complex *A, int bsize, complex *b, complex *x)
Nterm * extract_divisible_by_x(Nterm *&ff, int i)
void rawLaunchPT(PathTracker *PT, const Matrix *start_sols)
gmp_RRorNull rawGetSolutionRcondPT(PathTracker *PT, int solN)
const Matrix * rawGetAllSolutionsPT(PathTracker *PT)
Engine-boundary C API for the Numerical Algebraic Geometry subsystem.
void zero_complex_array(int n, typename Field::element_type *a)
gmp_CC toBigComplex(const CCC *C, ring_elem a)
void add_to_complex_array(int n, typename Field::element_type *a, const typename Field::element_type *b)
void multiply_complex_array_scalar(int n, typename Field::element_type *a, const typename Field::element_type b)
int degree_ring_elem(const PolyRing *R, ring_elem re)
ring_elem from_doubles(const CCC *C, double re, double im)
void negate_complex_array(int n, typename Field::element_type *a)
#define PROJECTIVE_NEWTON
double norm2_complex_array(int n, typename Field::element_type *a)
void copy_complex_array(int n, const typename Field::element_type *a, typename Field::element_type *b)
const CCC * cast_to_CCC(const Ring *R)
#define MAX_NUM_PATH_TRACKERS
Numerical Algebraic Geometry: homotopy continuation PathTracker and supporting numeric types.
Engine-side free module R^n over a Ring.
const Ring * get_ring() const
ring_elem elem(int i, int j) const
void set_entry(int r, int c, ring_elem a)
Mutable builder used to assemble an immutable Matrix one column (or one term) at a time.
gmp_RRorNull getSolutionLastT(int)
int track(const Matrix *)
static PathTracker * catalog[MAX_NUM_PATH_TRACKERS]
int getSolutionSteps(int)
void evaluate_slpHxt(int n, const complex *x0t0, complex *Hxt)
static PathTracker * make(const Matrix *)
double maxDegreeTo3halves
void evaluate_slpHxH(int n, const complex *x0t0, complex *HxH)
static int num_path_trackers
int getSolutionStatus(int)
gmp_RR dt_decrease_factor
void evaluate_slpHxtH(int n, const complex *x0t0, complex *HxtH)
int num_successes_before_increase
Matrix * getAllSolutions()
Matrix * refine(const Matrix *sols, gmp_RR tolerance, int max_corr_steps_refine=100)
gmp_RR infinity_threshold
Matrix * getSolution(int)
gmp_RR dt_increase_factor
gmp_RRorNull getSolutionRcond(int)
void text_out(buffer &o) const
Numerical homotopy-continuation path tracker for systems of polynomial equations.
Concrete PolyRingFlat subclass implementing ordinary commutative polynomial rings K[x_1,...
virtual const Ring * getCoefficients() const
virtual FreeModule * make_FreeModule() const
virtual const PolyRing * cast_to_PolyRing() const
virtual ring_elem copy(const ring_elem f) const =0
virtual bool multi_degree(const ring_elem f, monomial d) const
SLP< Field > * concatenate(const SLP< Field > *slp)
void evaluate(int n, const element_type *values, element_type *out)
void relative_to_absolute(int &aa, int cur_node)
void convert_to_absolute_position()
SLP< Field > * jacobian(bool makeHxH, SLP< Field > *&slpHxH, bool makeHxtH, SLP< Field > *&slpHxtH)
int poly_to_horner_slp(int n, gc_vector< int > &prog, gc_vector< element_type > &consts, Nterm *&f)
void stats_out(buffer &o) const
ComplexField::element_type element_type
static SLP< Field > * make(const PolyRing *, ring_elem)
int diffNodeInput(int n, int v, gc_vector< int > &prog)
static void make_nodes(element_type *&, int size)
static SLP< Field > * catalog[MAX_NUM_SLPs]
void(* compiled_fn)(element_type *, element_type *)
void text_out(buffer &o) const
gc_vector< int > node_index
bool is_relative_position
int diffPartReference(int n, int ref, int v, gc_vector< int > &prog)
static StraightLineProgram * make(const PolyRing *R, ring_elem e)
void evaluate(int n, const element_type *values, element_type *out)
void text_out(buffer &o) const
double getimaginary() const
Engine-wide include prelude — a single point of truth for portability shims.
mpfr_srcptr moveTo_gmpRR(mpfr_ptr _z)
int zgesvd_(char *jobU, char *jobV, int *rows, int *cols, double *A, int *ldA, double *Sigma, double *U, int *ldU, double *VT, int *ldVT, double *w, int *lwork, double *rwork, int *info)
int zgesv_(int *n, int *nrhs, double *a, int *lda, int *ipiv, double *b, int *ldb, int *info)
Engine bridge into LAPACK for RR / CC dense linear algebra.
VALGRIND_MAKE_MEM_DEFINED & result(result)
#define getmemstructtype(S)
int M2_numericalAlgebraicGeometryTrace
M2_arrayint M2_makearrayint(int n)
MatrixConstructor — the mutable builder that produces an immutable Matrix.
Matrix — the engine's immutable homomorphism F -> G between free modules.
#define ALLOCATE_EXPONENTS(byte_len)
#define EXPONENT_BYTE_SIZE(nvars)
typename std::vector< T, gc_allocator< T > > gc_vector
a version of the STL vector, which allocates its backing memory with gc.
#define newarray_atomic(T, len)
Concrete commutative PolyRing — standard polynomial ring inheriting from PolyRingFlat.
RingElement — tagged (Ring*, ring_elem) pair, the engine's universal element type.
Singly linked-list node carrying one term of a polynomial-ring element.
void make(int m, const complex *s_s)
One numerical solution produced by a PathTracker run, with the full per-path diagnostic record.