48#include <boost/serialization/vector.hpp>
75 : num_vars_(num_vars), factors_highest_precision_(std::move(factors)), precision_(
DefaultPrecision())
78 for (
auto const& M : factors_highest_precision_)
79 assert(
static_cast<size_t>(M.cols()) == num_vars_ + 1 &&
80 "every products-of-linears coefficient matrix must have num_vars+1 columns");
86 size_t NumFunctions()
const {
return factors_highest_precision_.size(); }
91 std::vector<int> d; d.reserve(factors_highest_precision_.size());
92 for (
auto const& M : factors_highest_precision_) d.push_back(
static_cast<int>(M.rows()));
104 return !factors_highest_precision_.empty()
105 &&
static_cast<size_t>(factors_highest_precision_.front().cols()) == num_vars_;
120 throw std::runtime_error(
"ProductsOfLinearsBlock::Homogenize: block is already homogenized "
121 "(multiple affine variable groups are not yet supported for products-of-linears blocks)");
122 const Eigen::Index n =
static_cast<Eigen::Index
>(num_vars_);
123 for (
auto& M : factors_highest_precision_)
126 Mh.col(0) = M.col(n);
127 Mh.rightCols(n) = M.leftCols(n);
139 const Eigen::Index n =
static_cast<Eigen::Index
>(num_vars_);
140 for (
auto const& M : factors_highest_precision_)
141 for (Eigen::Index r = 0; r < M.rows(); ++r)
142 if (M(r, n).real() != 0 || M(r, n).imag() != 0)
155 std::vector<Mat<complex_mp>>
const&
Factors()
const {
return factors_highest_precision_; }
161 for (
auto const& M : factors_highest_precision_)
163 out <<
" f_" << row++ <<
" = ";
164 const Eigen::Index k = M.rows();
167 out <<
"prod of " << k <<
" linear form" << (k == 1 ?
"" :
"s");
175 for (Eigen::Index r = 0; r < k; ++r)
177 out << (r ?
" * " :
"") <<
"(";
204 if (precision_==new_precision)
208 auto& wm = std::get<std::vector<Mat<complex_mp>>>(factors_working_);
209 for (
size_t i = 0; i < wm.size(); ++i)
210 for (Eigen::Index r = 0; r < wm[i].rows(); ++r)
211 for (Eigen::Index c = 0; c < wm[i].cols(); ++c)
213 wm[i](r, c).precision(new_precision);
214 if (new_precision > precision_)
215 wm[i](r, c) = factors_highest_precision_[i](r, c);
218 precision_ = new_precision;
229 template <
typename T>
233 const auto& W = Working<T>();
236 const Vec<T> aug = Augment<T>(vars);
241 for (
size_t i = 0; i < W.size(); ++i)
243 const Vec<T> fvals = W[i] * aug;
245 for (Eigen::Index r = 0; r < fvals.size(); ++r)
247 result(
static_cast<Eigen::Index
>(i)) = val;
259 template <
typename T>
263 const auto& W = Working<T>();
264 const Vec<T> aug = Augment<T>(vars);
274 for (
size_t i = 0; i < W.size(); ++i)
277 const Eigen::Index k = M.rows();
281 J.row(
static_cast<Eigen::Index
>(i)).setZero();
285 const Vec<T> fvals = M * aug;
296 for (Eigen::Index r = 0; r < k; ++r) { weight(r) = acc; acc *= fvals(r); }
298 for (Eigen::Index r = k - 1; r >= 0; --r) { weight(r) *= acc; acc *= fvals(r); }
303 J.row(
static_cast<Eigen::Index
>(i)) = weight.transpose() * M.leftCols(
static_cast<Eigen::Index
>(num_vars_));
311 template <
typename T>
323 template <
typename T>
324 void SyncPrecision(
Vec<T> const& vars)
const
326 if constexpr (!std::is_same<T, complex_dbl>::value)
337 template <
typename T>
338 const std::vector<Mat<T>>& Working()
const
340 return std::get<std::vector<Mat<T>>>(factors_working_);
343 template <
typename T>
348 Vec<T> aug(
static_cast<Eigen::Index
>(num_vars_ + 1));
349 aug.head(
static_cast<Eigen::Index
>(num_vars_)) = vars;
351 if constexpr (!std::is_same<T, complex_dbl>::value)
352 one.precision(precision_);
353 aug(
static_cast<Eigen::Index
>(num_vars_)) = one;
357 void BuildWorking()
const
359 auto& wd = std::get<std::vector<Mat<complex_dbl>>>(factors_working_);
360 auto& wm = std::get<std::vector<Mat<complex_mp>>>(factors_working_);
361 const size_t n = factors_highest_precision_.size();
364 for (
size_t i = 0; i < n; ++i)
366 const auto& M = factors_highest_precision_[i];
367 wd[i].resize(M.rows(), M.cols());
368 wm[i].resize(M.rows(), M.cols());
369 for (Eigen::Index r = 0; r < M.rows(); ++r)
370 for (Eigen::Index c = 0; c < M.cols(); ++c)
373 wm[i](r, c) = M(r, c);
379 std::vector<Mat<complex_mp>> factors_highest_precision_;
380 mutable std::tuple<std::vector<Mat<complex_dbl>>, std::vector<Mat<complex_mp>>> factors_working_;
381 mutable unsigned precision_;
385 template <
typename Archive>
386 void serialize(Archive& ar,
const unsigned )
390 ar & factors_highest_precision_;
391 ar & std::get<0>(factors_working_);
392 ar & std::get<1>(factors_working_);
void EvalInPlace(Eigen::Ref< Vec< T > > result, Vec< T > const &vars, T const &) const
Evaluate the block's function values into a caller-provided segment.
Definition products_of_linears_block.hpp:230
bool DependsOnPathVariable() const
Products of linears do not depend on the path variable.
Definition products_of_linears_block.hpp:187
std::vector< Mat< complex_mp > > const & Factors() const
The master (highest-precision) coefficient matrices, one per function; matrix i is (number of factors...
Definition products_of_linears_block.hpp:155
ProductsOfLinearsBlock(size_t num_vars, std::vector< Mat< complex_mp > > factors)
Definition products_of_linears_block.hpp:74
std::vector< int > Degrees(VariableGroup const &) const
Per-function degrees with respect to a given variable group (same as the total degrees).
Definition products_of_linears_block.hpp:96
bool IsHomogeneous(VariableGroup const &) const
Homogeneous once Homogenize has run, or when every factor's constant column is zero (the form the m-h...
Definition products_of_linears_block.hpp:135
std::vector< int > Degrees() const
Each function is a product of its linear factors, so its degree is the factor count.
Definition products_of_linears_block.hpp:89
bool HasConstantJacobian() const
The Jacobian is not constant (it depends on x), unlike a slice.
Definition products_of_linears_block.hpp:190
bool IsHomogenized() const
Whether Homogenize has folded the constant column onto a homogenizing variable.
Definition products_of_linears_block.hpp:102
size_t NumFunctions() const
Number of functions (rows the block contributes to the system).
Definition products_of_linears_block.hpp:86
void Describe(std::ostream &out, size_t &row, VariableGroup const &vars, bool verbose) const
Human-facing description: terse shows prod of k linear forms; verbose shows the actual product of aff...
Definition products_of_linears_block.hpp:159
bool IsPolynomial(VariableGroup const &) const
Always true: a product of linear forms is a polynomial.
Definition products_of_linears_block.hpp:147
void Precision(unsigned new_precision) const
Set the working precision; recasts the mpfr working coefficients from the master.
Definition products_of_linears_block.hpp:199
friend class boost::serialization::access
Definition products_of_linears_block.hpp:383
void TimeDerivInPlace(Eigen::Ref< Vec< T > > result, Vec< T > const &, T const &) const
Time-derivative into a caller-provided segment.
Definition products_of_linears_block.hpp:312
size_t NumVariables() const
Number of variables the block expects in the input vector.
Definition products_of_linears_block.hpp:150
void Differentiate() const
Analytic block: nothing symbolic to differentiate.
Definition products_of_linears_block.hpp:193
void JacobianInPlace(Eigen::Ref< Mat< T > > J, Vec< T > const &vars, T const &) const
Evaluate the block's Jacobian (d f_i / d x_j) into a caller-provided block.
Definition products_of_linears_block.hpp:260
ProductsOfLinearsBlock()
Definition products_of_linears_block.hpp:66
unsigned Precision() const
Get the block's current working precision.
Definition products_of_linears_block.hpp:196
void Homogenize(VariableGroup const &, std::shared_ptr< node::Variable > const &)
Homogenize with respect to an affine variable group: fold each factor's constant column onto the homo...
Definition products_of_linears_block.hpp:117
Small shared helpers for the per-block Describe methods – the human-facing printing of a block-compos...
Bertini extensions of the Eigen linear algebra library.
void PrintLinearFormVerbose(std::ostream &out, Mat< complex_mp > const &M, Eigen::Index r, VariableGroup const &vars, size_t num_vars, bool homogeneous)
One affine linear form, row r of an augmented coefficient matrix M (num_vars+1 cols affine,...
Definition describe.hpp:92
Definition blend_block.hpp:75
Definition algorithm_builder.hpp:36
constexpr unsigned DoublePrecision()
The number of digits considered "double precision" (16).
Definition num_traits.hpp:152
std::complex< double > complex_dbl
The double-precision complex number type.
Definition double_extensions.hpp:47
Eigen::Matrix< NumT, Eigen::Dynamic, 1 > Vec
A dynamically-sized column vector of NumT.
Definition eigen_extensions.hpp:296
std::vector< std::shared_ptr< node::Variable > > VariableGroup
An ordered group of variables (the unit of homogenization / variable grouping).
Definition node.hpp:69
Eigen::Matrix< NumT, Eigen::Dynamic, Eigen::Dynamic > Mat
A dynamically-sized matrix of NumT.
Definition eigen_extensions.hpp:298
auto DefaultPrecision()
Get the global default precision (digits) for multiprecision numbers.
Definition mpfr_complex.hpp:135
unsigned Precision(Eigen::MatrixBase< Derived > const &v)
Get the precision of an Eigen object.
Definition eigen_extensions.hpp:339
Provides an Eigen-like NumTraits struct for querying traits of a number type.