Polyhedral Homotopy Continuation Method for solving sparse polynomial system, optimized by only tracing real zeros
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

356 lines
9.9 KiB

// This file is part of Bertini 2.
//
// number.hpp is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
//(at your option) any later version.
//
// number.hpp is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with number.hpp. If not, see <http://www.gnu.org/licenses/>.
//
// Copyright(C) 2015 - 2023 by Bertini2 Development Team
//
// See <http://www.gnu.org/licenses/> for a copy of the license,
// as well as COPYING. Bertini2 is provided with permitted
// additional terms in the b2/licenses/ directory.
// individual authors of this file include:
// James Collins
// West Texas A&M University
// Spring, Summer 2015
//
//
// silviana amethyst
// University of Wisconsin - Eau Claire
//
// Created by Collins, James B. on 4/30/15.
//
//
// number.hpp: Declares the class Number.
/**
\file number.hpp
\brief Provides the Number Node types, including Rational, Float, and Integer
*/
#ifndef BERTINI_NODE_NUMBER_HPP
#define BERTINI_NODE_NUMBER_HPP
#include "function_tree/symbols/symbol.hpp"
namespace bertini {
namespace node {
/**
\brief Abstract Number type from which other Numbers derive.
This class represents constant leaves to a function tree. FreshEval simply
returns the value of the constant.
*/
class Number : public virtual Symbol {
public:
virtual ~Number() = default;
void Reset() const override;
/**
\brief Get the degree of this node.
The degree of a number is always 0. It's a number.
*/
inline int Degree(
std::shared_ptr<Variable> const& v = nullptr) const override {
return 0;
}
/**
\brief Get the degree of this node.
The degree of a number is always 0. It's a number.
*/
inline int Degree(VariableGroup const& vars) const override { return 0; }
/**
\brief Get the multidegree of this node.
The degree of a number is always 0. It's a number.
*/
inline std::vector<int> MultiDegree(
VariableGroup const& vars) const override {
return std::vector<int>(vars.size(), 0);
}
/**
\brief Homogenize this node.
Homogenization of a number is a trivial operation. Don't do anything.
*/
void Homogenize(VariableGroup const& vars,
std::shared_ptr<Variable> const& homvar) override {}
/**
\brief Is this node homogeneous?
Numbers are always homogeneous
*/
bool IsHomogeneous(
std::shared_ptr<Variable> const& v = nullptr) const override {
return true;
}
/**
Check for homogeneity, with respect to a variable group.
*/
bool IsHomogeneous(VariableGroup const& vars) const override { return true; }
/**
Change the precision of this variable-precision tree node.
\param prec the number of digits to change precision to.
*/
void precision(unsigned int prec) const override;
/**
\brief Differentiate a number.
*/
std::shared_ptr<Node> Differentiate(
std::shared_ptr<Variable> const& v = nullptr) const override;
protected:
private:
friend class boost::serialization::access;
template <typename Archive>
void serialize(Archive& ar, const unsigned version) {
ar& boost::serialization::base_object<Symbol>(*this);
}
};
/**
\brief Signed real Integer storage in an expression tree.
Signed real Integer storage in an expression tree. Consider using a Rational
type.
*/
class Integer : public virtual Number,
public virtual EnableSharedFromThisVirtual<Integer> {
public:
BERTINI_DEFAULT_VISITABLE()
Integer(Integer const&) = default;
~Integer() = default;
void print(std::ostream& target) const override;
template <typename... Ts>
static std::shared_ptr<Integer> Make(Ts&&... ts) {
return std::shared_ptr<Integer>(new Integer(ts...));
}
private:
// https://stackoverflow.com/questions/33933550/exception-bad-weak-ptr-while-shared-from-this
// struct MakeConstructorPublic;
explicit Integer(int val) : true_value_(val) {}
explicit Integer(mpz_int val) : true_value_(val) {}
explicit Integer(std::string const& val) : true_value_(val) {}
// Return value of constant
dbl FreshEval_d(
std::shared_ptr<Variable> const& diff_variable) const override;
void FreshEval_d(
dbl& evaluation_value,
std::shared_ptr<Variable> const& diff_variable) const override;
mpfr_complex FreshEval_mp(
std::shared_ptr<Variable> const& diff_variable) const override;
void FreshEval_mp(
mpfr_complex& evaluation_value,
std::shared_ptr<Variable> const& diff_variable) const override;
mpz_int true_value_;
friend class boost::serialization::access;
Integer() = default;
template <typename Archive>
void serialize(Archive& ar, const unsigned version) {
ar& boost::serialization::base_object<Number>(*this);
ar & true_value_;
}
};
// struct Integer::MakeConstructorPublic : public Integer {
// template <typename... Args>
// MakeConstructorPublic(Args&& ...args) :
// Integer(std::forward<Args>(args)...)
// {}
// };
/**
\brief Number type for storing floating point numbers within an expression tree.
Number type for storing floating point numbers within an expression tree. The
number passed in at construct time is stored as the true value, and evaluation
down or up samples from this 'true value'. Consider using a Rational or Integer
if possible.
*/
class Float : public virtual Number,
public virtual EnableSharedFromThisVirtual<Float> {
public:
BERTINI_DEFAULT_VISITABLE()
~Float() = default;
void print(std::ostream& target) const override;
template <typename... Ts>
static std::shared_ptr<Float> Make(Ts&&... ts) {
return std::shared_ptr<Float>(new Float(ts...));
}
private:
explicit Float(mpfr_complex const& val) : highest_precision_value_(val) {}
explicit Float(mpfr_float const& rval, mpfr_float const& ival = 0)
: highest_precision_value_(rval, ival) {}
explicit Float(std::string const& val) : highest_precision_value_(val) {}
explicit Float(std::string const& rval, std::string const& ival)
: highest_precision_value_(rval, ival) {}
dbl FreshEval_d(
std::shared_ptr<Variable> const& diff_variable) const override;
void FreshEval_d(
dbl& evaluation_value,
std::shared_ptr<Variable> const& diff_variable) const override;
mpfr_complex FreshEval_mp(
std::shared_ptr<Variable> const& diff_variable) const override;
void FreshEval_mp(
mpfr_complex& evaluation_value,
std::shared_ptr<Variable> const& diff_variable) const override;
mpfr_complex highest_precision_value_;
friend class boost::serialization::access;
Float() = default;
template <typename Archive>
void serialize(Archive& ar, const unsigned version) {
ar& boost::serialization::base_object<Number>(*this);
ar& const_cast<mpfr_complex&>(highest_precision_value_);
}
};
/**
\brief The Rational number type for Bertini2 expression trees.
The Rational number type for Bertini2 expression trees. The `true value' is
stored using two mpq_rational numbers from the Boost.Multiprecision library, and
the ratio is converted into a double or a mpfr_complex at evaluate time.
*/
class Rational : public virtual Number,
public virtual EnableSharedFromThisVirtual<Rational> {
public:
BERTINI_DEFAULT_VISITABLE()
using mpq_rational = bertini::mpq_rational;
Rational(int, int) = delete;
~Rational() = default;
/**
\brief Get a random complex rational node. Numerator and denominator will
have about 50 digits.
\see RandomRat()
*/
template <unsigned long Digits = 50>
static Rational Rand() {
return Rational(RandomRat<Digits>(), RandomRat<Digits>());
}
/**
\brief Get a random real rational node. Numerator and denominator will have
about 50 digits.
\see RandomRat()
*/
template <int Digits = 50>
static Rational rand_real() {
return Rational(RandomRat<Digits>(), 0);
}
void print(std::ostream& target) const override;
template <typename... Ts>
static std::shared_ptr<Rational> Make(Ts&&... ts) {
return std::shared_ptr<Rational>(new Rational(ts...));
}
private:
explicit Rational(int val) : true_value_real_(val), true_value_imag_(0) {}
explicit Rational(int val_real_numerator, int val_real_denomenator,
int val_imag_numerator, int val_imag_denomenator)
: true_value_real_(val_real_numerator, val_real_denomenator),
true_value_imag_(val_imag_numerator, val_imag_denomenator) {}
explicit Rational(std::string val)
: true_value_real_(val), true_value_imag_(0) {}
explicit Rational(std::string val_real, std::string val_imag)
: true_value_real_(val_real), true_value_imag_(val_imag) {}
explicit Rational(mpq_rational const& val_real,
mpq_rational const& val_imag = 0)
: true_value_real_(val_real), true_value_imag_(val_imag) {}
// Return value of constant
dbl FreshEval_d(
std::shared_ptr<Variable> const& diff_variable) const override;
void FreshEval_d(
dbl& evaluation_value,
std::shared_ptr<Variable> const& diff_variable) const override;
mpfr_complex FreshEval_mp(
std::shared_ptr<Variable> const& diff_variable) const override;
void FreshEval_mp(
mpfr_complex& evaluation_value,
std::shared_ptr<Variable> const& diff_variable) const override;
mpq_rational true_value_real_, true_value_imag_;
Rational() = default;
friend class boost::serialization::access;
template <typename Archive>
void serialize(Archive& ar, const unsigned version) {
ar& boost::serialization::base_object<Number>(*this);
ar& const_cast<mpq_rational&>(true_value_real_);
ar& const_cast<mpq_rational&>(true_value_imag_);
}
};
} // namespace node
} // namespace bertini
#endif