Add files

This commit is contained in:
2025-01-14 01:15:48 +01:00
commit 2f9fcec55b
406 changed files with 87154 additions and 0 deletions

View File

@@ -0,0 +1,430 @@
//This file is part of Bertini 2.
//
//bertini2/io/parsers.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.
//
//bertini2/io/parsing/classic_utilities.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 bertini2/io/parsing/classic_utilities.hpp. If not, see <http://www.gnu.org/licenses/>.
//
// Copyright(C) 2015 - 2017 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.
/**
\file bertini2/io/parsing/classic_utilities.hpp
\brief Provides utility functions for parsing classic bertini input files.
*/
#pragma once
#include "bertini2/io/parsing/qi_files.hpp"
#include "bertini2/io/file_utilities.hpp"
namespace bertini {
namespace parsing {
namespace classic {
namespace qi = ::boost::spirit::qi;
namespace ascii = ::boost::spirit::ascii;
/**
\class SplitInputFile
\brief Storage class for input file that splits up the config portion from the input portion.
## Use
SplitFileInputConfig parser return an instance of this class. The user can then parse the config and input portions separately using the appropriate parser.
*/
class SplitInputFile
{
public:
std::string Config() const
{
return config_;
}
std::string Input() const
{
return input_;
}
bool Readable() const
{
return readable_;
}
void SetInput(std::string new_input)
{
input_ = new_input;
}
void SetConfig(std::string new_config)
{
config_ = new_config;
}
void SetConfigInput(std::string c, std::string i)
{
config_ = c;
input_ = i;
}
void SetReadable(bool read)
{
readable_ = read;
}
// void StripComments()
// {
// std::string::const_iterator iter = config_.begin();
// std::string::const_iterator end = config_.end();
//
// CommentStripper<std::string::const_iterator> S;
//
// phrase_parse(iter, end, S,boost::spirit::ascii::space, config_);
//
// iter = input_.begin();
// end = input_.end();
//
// phrase_parse(iter, end, S,boost::spirit::ascii::space, input_);
// }
friend std::ostream& operator<<(std::ostream & out, SplitInputFile const& printme)
{
out << "--------config-----------\n\n" << printme.Config() << "\n\n-------input--------\n\n" << printme.Input();
return out;
}
private:
std::string config_;
std::string input_;
bool readable_ = true; //Input file can be split accurately
}; //re: SplitInputFile class
/**
Qi Parser object for parsing text into the SplitInputfile class. This ensures we can provide backwards compatibility with Bertini Classic input files.
To use this parser, construct an object of its type, then use it to parse.
\code
System sys;
std::string str = "variable_group x, y, z; \nfunction f1, f2;\n f1 = x*y*z;\n f2 = x+y+z;\n";
std::string::const_iterator iter = str.begin();
std::string::const_iterator end = str.end();
bertini::SystemParser<std::string::const_iterator> S;
bool s = phrase_parse(iter, end, S,boost::spirit::ascii::space, sys);
\endcode
\brief Qi Parser object for parsing text into the SplitInputFile class.
CON END IN END (1 1 1 1) 15
CON END IN -- (1 1 1 0) 14
CON END -- END (1 1 0 1) 13
CON END -- -- (1 1 0 0) 12
CON -- IN END (1 0 1 1) 11
CON -- IN -- (1 0 1 0) 10
-- -- IN END (0 0 1 1) 3
-- -- IN -- (0 0 1 0) 2
-- -- --END (0 0 0 1) 1
-- -- -- -- (0 0 0 0) 0
*/
template<typename Iterator, typename Skipper = ascii::space_type> //boost::spirit::unused_type
struct SplitInputFileParser : qi::grammar<Iterator, SplitInputFile(), Skipper>
{
SplitInputFileParser() : SplitInputFileParser::base_type(root_rule_, "SplitInputFile")
{
namespace phx = boost::phoenix;
using qi::_1;
using qi::_2;
using qi::_3;
using qi::_4;
using qi::_val;
using qi::eps;
using qi::lit;
using qi::char_;
using qi::omit;
using boost::spirit::lexeme;
using boost::spirit::as_string;
using boost::spirit::ascii::no_case;
root_rule_.name("SplitInputFile_root_rule");
root_rule_ = both_ | unreadable_ |only_input_ ;
// NOTE ON CONVENTIONS CURRENTLY USED:
// the various rules are constructed to obtain the text BEFORE the named marker, so e.g, rule config_ gets all text in the string before 'CONFIG'. similarly for 'END;' and 'INPUT'.
both_.name("have_both_config_and_input");
both_ = (
(omit[config_] >> end_ >> omit[input_] >> end_ >> omit[no_decl_]) [phx::bind(&SplitInputFile::SetConfigInput, _val, _1, _2)]// 15
|
(omit[config_] >> end_ >> omit[input_] >> no_decl_) [phx::bind(&SplitInputFile::SetConfigInput, _val, _1, _2)] // 14
|
(omit[config_] >> end_ >> end_ >> omit[no_decl_]) [phx::bind(&SplitInputFile::SetConfigInput, _val, _1, _2)] // 13
|
(omit[config_] >> input_ >> end_ >> omit[no_decl_]) [phx::bind(&SplitInputFile::SetConfigInput, _val, _1, _2)] // 11
|
(omit[config_] >> end_ >> no_decl_) [phx::bind(&SplitInputFile::SetConfigInput, _val, _1, _2)] // 12
|
(omit[config_] >> input_ >> no_decl_) [phx::bind(&SplitInputFile::SetConfigInput, _val, _1, _2)] // 10
)
;
// the rule for number 11 does not currently correctly parse text which matches it... why???
//this attempt for the both_ rule doesn't work because the ends are optional...
// (omit[config_] >> end_ >> omit[input_] >> end_ >> omit[no_decl_]) [phx::bind(&SplitInputFile::SetConfigInput, _val, _1, _2)]
// |
// (omit[config_] >> omit[!end_] >> input_ >> end_ >> omit[no_decl_]) [phx::bind(&SplitInputFile::SetConfigInput, _val, _1, _2)]
// |
// (omit[config_] >> end_ >> omit[!input_] >> end_ >> omit[no_decl_]) [phx::bind(&SplitInputFile::SetConfigInput, _val, _1, _2)]
// |
// (omit[config_] >> omit[!end_] >> input_ >> no_decl_) [phx::bind(&SplitInputFile::SetConfigInput, _val, _1, _2)]
// |
// (omit[config_] >> end_ >> omit[!input_] >> omit[!end_] >> no_decl_) [phx::bind(&SplitInputFile::SetConfigInput, _val, _1, _2)]
// )
only_input_.name("have_only_input");
only_input_ = (
(omit[input_] >> end_ >> omit[no_decl_]) // 3
|
(omit[input_] >> no_decl_) // 2
|
(end_ >> omit[no_decl_]) // 1
|
(no_decl_) // 0
)
[phx::bind(&SplitInputFile::SetInput, _val, _1)];
unreadable_.name("unreadable_input"); //9 and 4 same as 12 and 1 to parser
unreadable_ = (
(omit[config_] >> no_decl_) // 8
|
(end_ >> omit[input_] >> end_ >> omit[no_decl_]) // 7
|
(end_ >> omit[input_] >> omit[no_decl_]) // 6
|
(end_ >> end_ >> omit[no_decl_]) // 5
)
[phx::bind(&SplitInputFile::SetReadable, _val, false)];
config_.name("config_");
config_ = no_case[*(char_ - "CONFIG") >> "CONFIG"];
end_.name("end_");
end_ = no_case[lexeme[*(char_ - "END;")] >> "END;"];
input_.name("input_");
input_ = no_case[lexeme[*(char_ - "INPUT")] >> "INPUT"];
no_decl_.name("no_decl_");
no_decl_ = lexeme[*(char_)];
// debug(root_rule_);
// debug(both_); debug(only_input_);
// debug(config_);
// debug(end_);
// debug(input_);
// debug(no_decl_);
// BOOST_SPIRIT_DEBUG_NODES((root_rule_)
// (both_) (only_input_)
// (config_) (end_) (input_)
// (no_decl_) )
using phx::val;
using phx::construct;
using namespace qi::labels;
qi::on_error<qi::fail>
( root_rule_ ,
std::cout<<
val("config/input split parser could not complete parsing. Expecting ")<<
_4<<
val(" here: ")<<
construct<std::string>(_3,_2)<<
std::endl
);
}
private:
qi::rule<Iterator, SplitInputFile(), ascii::space_type > root_rule_, both_, only_input_, unreadable_;
qi::rule<Iterator, ascii::space_type, std::string()> end_, input_, no_decl_;
qi::rule<Iterator, ascii::space_type> config_;
};
/**
Qi Parser object for removing comments from a line of text and then returns the uncommented line.
To use this parser, construct an object of its type, then use it to parse.
*/
template<typename Iterator, typename Skipper = ascii::space_type> //boost::spirit::unused_type
struct CommentStripper : qi::grammar<Iterator, std::string(), Skipper>
{
CommentStripper() : CommentStripper::base_type(root_rule_, "CommentStripper")
{
namespace phx = boost::phoenix;
using qi::_1;
using qi::_2;
using qi::_3;
using qi::_4;
using qi::_val;
using qi::eol;
using qi::eoi;
using qi::eps;
using qi::lit;
using qi::char_;
using qi::omit;
using boost::spirit::lexeme;
using boost::spirit::as_string;
root_rule_.name("CommentStripper_root_rule");
root_rule_ = eps[_val = ""] >> *line_[_val = _val + _1 + "\n"] >> -last_line_[_val = _val + _1 + "\n"];//+line_ | qi::eoi;
line_.name("line_of_commented_input");
line_ = lexeme[*(char_ - eol - "%") >> omit[-( "%" >> lexeme[*(char_ - eol)] )] >> (eol ) ];
last_line_.name("line_of_commented_input_with_no_eol");
last_line_ = lexeme[*(char_ - "%") >> omit[-( "%" >> lexeme[*(char_ - eol)] )]] ;
// debug(root_rule_);
// debug(line_);
// debug(last_line_);
//
// BOOST_SPIRIT_DEBUG_NODES((root_rule_)
// (line_) (last_line_) )
using phx::val;
using phx::construct;
using namespace qi::labels;
qi::on_error<qi::fail>
( root_rule_ ,
std::cout<<
val("config/input split parser could not complete parsing. Expecting ")<<
_4<<
val(" here: ")<<
construct<std::string>(_3,_2)<<
std::endl
);
}
private:
qi::rule<Iterator, std::string(), ascii::space_type > root_rule_;
qi::rule<Iterator, ascii::space_type, std::string()> line_, last_line_;
};
SplitInputFile ParseInputFile(std::string str_input_file)
{
std::string::const_iterator iter = str_input_file.begin();
std::string::const_iterator end = str_input_file.end();
std::string uncommented_str_input;
CommentStripper<std::string::const_iterator> commentparser;
phrase_parse(iter, end, commentparser,boost::spirit::ascii::space, uncommented_str_input);
iter = uncommented_str_input.begin();
end = uncommented_str_input.end();
SplitInputFileParser<std::string::const_iterator> spliter;
SplitInputFile input_file;
phrase_parse(iter, end, spliter,boost::spirit::ascii::space, input_file);
return input_file;
}
/**
\brief Function for splitting a Bertini Classic style input file into `config` and `input`.
*/
std::tuple<std::string, std::string> SplitIntoConfigAndInput(Path const& input_file)
{
auto file_as_string = FileToString(input_file);
SplitInputFileParser<std::string::const_iterator> parser;
SplitInputFile config_and_input;
std::string::const_iterator iter = file_as_string.begin();
std::string::const_iterator end = file_as_string.end();
phrase_parse(iter, end, parser, boost::spirit::ascii::space, config_and_input);
return std::make_tuple(config_and_input.Config(), config_and_input.Input());
}
/**
\brief Function for splitting a Bertini Classic style input file into `config` and `input`.
*/
void SplitIntoConfigAndInput(std::string & config_section, std::string & input_section, Path const& input_file)
{
std::tie(config_section, input_section) = SplitIntoConfigAndInput(input_file);
}
} // re: namespace classic
}// re: namespace parsing
}// re: namespace bertini

View File

@@ -0,0 +1,70 @@
//This file is part of Bertini 2.
//
//bertini2/io/parsers.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.
//
//bertini2/io/parsing/function_parsers.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 bertini2/io/parsing/function_parsers.hpp. If not, see <http://www.gnu.org/licenses/>.
//
// Copyright(C) 2015 - 2017 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.
/**
\file bertini2/io/parsing/function_parsers.hpp
\brief Provides the parsers for functions in bertini2.
*/
#pragma once
#include "bertini2/io/parsing/function_rules.hpp"
namespace bertini {
namespace parsing {
namespace classic {
template <typename Iterator>
bool parse(Iterator first, Iterator last, std::shared_ptr<bertini::node::Node>& func)
{
using boost::spirit::qi::double_;
using boost::spirit::qi::_1;
using boost::spirit::qi::phrase_parse;
using boost::spirit::ascii::space;
using boost::phoenix::ref;
FunctionParser<Iterator> S;
std::shared_ptr<bertini::node::Node> f{};
bool r = phrase_parse(first, last,
S,
space,
f);
if (!r || first != last) // fail if we did not get a full match
return false;
func = f;
return r;
}
} // re: namespace classic
}// re: namespace parsing
}// re: namespace bertini

View File

@@ -0,0 +1,309 @@
//This file is part of Bertini 2.
//
//bertini2/io/parsers.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.
//
//bertini2/io/parsing/function_rules.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 bertini2/io/parsing/function_rules.hpp. If not, see <http://www.gnu.org/licenses/>.
//
// Copyright(C) 2015 - 2017 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.
/**
\file bertini2/io/parsing/function_rules.hpp
\brief Provides the parsing rules for functions in bertini2.
*/
#pragma once
#include "bertini2/io/parsing/qi_files.hpp"
#include "bertini2/function_tree/node.hpp"
#include "bertini2/function_tree/roots/function.hpp"
#include "bertini2/function_tree/operators/arithmetic.hpp"
#include "bertini2/function_tree/operators/trig.hpp"
#include "bertini2/function_tree/symbols/number.hpp"
#include "bertini2/function_tree/symbols/variable.hpp"
#include "bertini2/io/parsing/number_rules.hpp"
// see the following link for reading from arbitrary streams without putting the content into a std::string first
//http://boost-spirit.com/home/articles/qi-example/tracking-the-input-position-while-parsing/
namespace {
// this solution for *lazy* make shared comes from the SO forum, asked by polytheme, answered by user sehe.
// https://stackoverflow.com/questions/21516201/how-to-create-boost-phoenix-make-shared
// post found using google search terms `phoenix construct shared_ptr`
// the code has been adapted slightly to fit the naming conventions of this project.
template <typename T>
struct MakeSharedFunctor
{
template <typename... A>
struct result
{
typedef std::shared_ptr<T> type;
};
template <typename... A>
typename result<A...>::type operator()(A&&... a) const
{
return T::Make(std::forward<A>(a)...);
}
};
template <typename T>
using make_shared_ = boost::phoenix::function<MakeSharedFunctor<T> >;
}
//////
//
// the following code adapts the trig functions and other special functions to be phoenix-callable.
//
/////////
// http://www.boost.org/doc/libs/1_58_0/libs/phoenix/doc/html/phoenix/modules/function/adapting_functions.html
//
// form is as follows:
//
//BOOST_PHOENIX_ADAPT_FUNCTION(
// RETURN_TYPE
// , LAZY_FUNCTION
// , FUNCTION
// , FUNCTION_ARITY
// )
BOOST_PHOENIX_ADAPT_FUNCTION(std::shared_ptr<bertini::node::Node>, cos_lazy, cos, 1);
BOOST_PHOENIX_ADAPT_FUNCTION(std::shared_ptr<bertini::node::Node>, sin_lazy, sin, 1);
BOOST_PHOENIX_ADAPT_FUNCTION(std::shared_ptr<bertini::node::Node>, tan_lazy, tan, 1);
BOOST_PHOENIX_ADAPT_FUNCTION(std::shared_ptr<bertini::node::Node>, log_lazy, log, 1);
BOOST_PHOENIX_ADAPT_FUNCTION(std::shared_ptr<bertini::node::Node>, exp_lazy, exp, 1);
BOOST_PHOENIX_ADAPT_FUNCTION(std::shared_ptr<bertini::node::Node>, sqrt_lazy, sqrt, 1);
namespace bertini {
namespace parsing {
namespace classic {
namespace qi = ::boost::spirit::qi;
namespace ascii = ::boost::spirit::ascii;
/**
A Qi grammar parser for parsing text into function trees. Currently called from the SystemParser.
\todo Improve error detection and reporting for the FunctionParser.
\brief A Qi grammar parser for parsing text into function trees.
This parser could not have been written without the generous help of SO user sehe.
*/
template<typename Iterator>
struct FunctionParser : qi::grammar<Iterator, std::shared_ptr<node::Node>(), boost::spirit::ascii::space_type>
{
using Node = node::Node;
using Function = node::Function;
using Float = node::Float;
using Integer = node::Integer;
using Rational = node::Rational;
FunctionParser(qi::symbols<char,std::shared_ptr<Node> > * encountered_symbols) : FunctionParser::base_type(root_rule_,"FunctionParser")
{
namespace phx = boost::phoenix;
using qi::_1;
using qi::_2;
using qi::_3;
using qi::_4;
using qi::_val;
using qi::eps;
using qi::lit;
using std::pow;
using ::pow;
root_rule_.name("function_");
root_rule_ = expression_ [ _val = make_shared_<Function>()(_1)];
///////////////////
expression_.name("expression_");
expression_ =
term_ [_val = _1]
>> *( (lit('+') > term_ [_val += _1])
| (lit('-') > term_ [_val -= _1])
)
;
term_.name("term_");
term_ =
factor_ [_val = _1]
>> *( (lit('*') > factor_ [_val *= _1])
| (lit('/') > factor_ [_val /= _1])
)
;
factor_.name("factor_");
factor_ =
exp_elem_ [_val = _1]
>> *(lit('^') // any number of ^somethings
> exp_elem_ [ phx::bind( []
(std::shared_ptr<Node> & B, std::shared_ptr<Node> P)
{
B = pow(B,P);
},
_val,_1)] )
;
exp_elem_.name("exp_elem_");
exp_elem_ =
(symbol_ >> !qi::alnum) [_val = _1]
| ( '(' > expression_ [_val = _1] > ')' ) // using the > expectation here.
| (lit('-') > expression_ [_val = -_1])
| (lit('+') > expression_ [_val = _1])
| (lit("sin") > '(' > expression_ [_val = sin_lazy(_1)] > ')' )
| (lit("cos") > '(' > expression_ [_val = cos_lazy(_1)] > ')' )
| (lit("tan") > '(' > expression_ [_val = tan_lazy(_1)] > ')' )
| (lit("exp") > '(' > expression_ [_val = exp_lazy(_1)] > ')' )
| (lit("log") > '(' > expression_ [_val = log_lazy(_1)] > ')' )
| (lit("sqrt") > '(' > expression_ [_val = sqrt_lazy(_1)] > ')' )
;
symbol_.name("symbol_");
symbol_ %=
(*encountered_symbols) // the star here is the dereferencing of the encountered_symbols parameter to the constructor.
|
number_
;
number_.name("number_");
number_ =
mpfr_rules_.long_number_string_ [ _val = make_shared_<Float>()(_1) ]
|
mpfr_rules_.integer_string_ [ _val = make_shared_<Integer>()(_1) ];
using qi::on_error;
using boost::phoenix::val;
using boost::phoenix::construct;
on_error<qi::fail>
(
root_rule_
, std::cout
<< val("Function parser error: expecting ")
<< _4
<< val(" here: \"")
<< construct<std::string>(_3, _2)
<< val("\"")
<< std::endl
);
// debug(root_rule_);
// debug(expression_);
// debug(term_);
// debug(factor_);
// debug(exp_elem_);
// debug(number_);
// debug(number_with_no_point_);
// debug(number_with_digits_after_point_);
// debug(number_with_digits_before_point_);
// debug(exponent_notation_);
}
qi::rule<Iterator, std::shared_ptr<Node>(), ascii::space_type > root_rule_;
// the rule for kicking the entire thing off
qi::rule<Iterator, std::shared_ptr<Node>(), ascii::space_type> expression_, term_, factor_, exp_elem_;
// rules for how to turn +-*/^ into operator nodes.
qi::rule<Iterator, std::shared_ptr<Node>(), ascii::space_type > symbol_;
// any of the variables and numbers will be symbols.
qi::rule<Iterator, std::shared_ptr<Node>(), ascii::space_type > variable_; // finds a previously encountered number, and associates the correct variable node with it.
// the number_ rule wants to find strings from the various other number_ rules, and produces a Number node
qi::rule<Iterator, std::shared_ptr<Node>(), ascii::space_type > number_;
parsing::rules::LongNum<Iterator> mpfr_rules_;
};
} // re: namespace classic
} // re: namespace parsing
} // re: namespace bertini

View File

@@ -0,0 +1,284 @@
//This file is part of Bertini 2.
//
//bertini2/io/parsers.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.
//
//bertini2/io/parsing/number_parsers.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 bertini2/io/parsing/number_parsers.hpp. If not, see <http://www.gnu.org/licenses/>.
//
// Copyright(C) 2015 - 2017 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.
/**
\file bertini2/io/parsing/number_parsers.hpp
\brief Provides parsers for numbers in bertini.
*/
#pragma once
#include "bertini2/io/parsing/number_rules.hpp"
namespace bertini{
namespace parsing{
namespace classic{
template<typename Iterator, typename Skipper = ascii::space_type>
struct MpfrFloatParser : qi::grammar<Iterator, mpfr_float(), boost::spirit::ascii::space_type>
{
MpfrFloatParser() : MpfrFloatParser::base_type(root_rule_,"MpfrFloatParser")
{
using std::max;
namespace phx = boost::phoenix;
using qi::_1;
using qi::_2;
using qi::_3;
using qi::_4;
using qi::_val;
root_rule_.name("mpfr_float");
root_rule_ = mpfr_rules_.number_string_
[ phx::bind(
[]
(mpfr_float & B, std::string const& P)
{
using std::max;
auto prev_prec = DefaultPrecision();
auto asdf = max(prev_prec,LowestMultiplePrecision());
auto digits = max(P.size(),static_cast<decltype(P.size())>(asdf));
B.precision(digits);
B = mpfr_float(P,digits);
},
_val,_1
)
];
using phx::val;
using phx::construct;
using namespace qi::labels;
qi::on_error<qi::fail>
( root_rule_ ,
std::cout<<
val("mpfr_float parser could not complete parsing. Expecting ")<<
_4<<
val(" here: ")<<
construct<std::string>(_3,_2)<<
std::endl
);
}
qi::rule<Iterator, mpfr_float(), Skipper > root_rule_;
rules::LongNum<Iterator> mpfr_rules_;
};
template<typename Iterator, typename Skipper = ascii::space_type>
struct MpfrComplexParser : qi::grammar<Iterator, mpfr_complex(), boost::spirit::ascii::space_type>
{
MpfrComplexParser() : MpfrComplexParser::base_type(root_rule_,"MpfrComplexParser")
{
using std::max;
namespace phx = boost::phoenix;
using qi::_1;
using qi::_2;
using qi::_val;
root_rule_ =
(mpfr_float_ >> mpfr_float_)
[ phx::bind(
[]
(mpfr_complex & B, mpfr_float const& P, mpfr_float const& Q)
{
auto prev_prec = DefaultPrecision();
auto digits = max(P.precision(),Q.precision());
B.precision(digits);
B.real(P);
B.imag(Q);
},
_val,_1,_2
)
];
}
qi::rule<Iterator, mpfr_complex(), Skipper > root_rule_;
MpfrFloatParser<Iterator> mpfr_float_;
};
template <typename Iterator>
static bool parse(Iterator first, Iterator last, double& c)
{
using boost::spirit::qi::double_;
using boost::spirit::qi::_1;
using boost::spirit::qi::phrase_parse;
using boost::spirit::ascii::space;
using boost::phoenix::ref;
double rN = 0.0;
bool r = phrase_parse(first, last,
(
double_[ref(rN) = _1]
),
space);
if (!r || first != last) // fail if we did not get a full match
return false;
c = rN;
return r;
}
template <typename Iterator>
static bool parse(Iterator first, Iterator last, std::complex<double>& c)
{
using boost::spirit::qi::double_;
using boost::spirit::qi::_1;
using boost::spirit::qi::phrase_parse;
using boost::spirit::ascii::space;
using boost::phoenix::ref;
double rN = 0.0;
double iN = 0.0;
bool r = phrase_parse(first, last,
(
double_[ref(rN) = _1]
>> -(double_[ref(iN) = _1])
| double_[ref(rN) = _1]
),
space);
if (!r || first != last) // fail if we did not get a full match
return false;
c = std::complex<double>(rN, iN);
return r;
}
template <typename Iterator>
static bool parse(Iterator first, Iterator last, mpfr_float& c)
{
using boost::spirit::qi::double_;
using boost::spirit::qi::_1;
using boost::spirit::qi::phrase_parse;
using boost::spirit::ascii::space;
using boost::phoenix::ref;
MpfrFloatParser<Iterator> S;
mpfr_float rN {0};
bool r = phrase_parse(first, last,
S,
space,
rN
);
if (!r || first != last) // fail if we did not get a full match
return false;
c.precision(rN.precision());
c = rN;
return r;
}
template <typename Iterator>
static bool parse(Iterator first, Iterator last, mpfr_complex& c)
{
using boost::spirit::qi::double_;
using boost::spirit::qi::_1;
using boost::spirit::qi::phrase_parse;
using boost::spirit::ascii::space;
using boost::phoenix::ref;
MpfrComplexParser<Iterator> S;
mpfr_complex rN {};
bool r = phrase_parse(first, last,
S,
space,
rN);
if (!r || first != last) // fail if we did not get a full match
return false;
c.precision(rN.precision());
c = rN;
return r;
}
} // re: namespace classic
namespace cplusplus{
template <typename Iterator>
static bool parse(Iterator first, Iterator last, double& c)
{
using boost::spirit::qi::double_;
using boost::spirit::qi::_1;
using boost::spirit::qi::phrase_parse;
using boost::spirit::ascii::space;
using boost::phoenix::ref;
double rN = 0.0;
bool r = phrase_parse(first, last,
(
double_[ref(rN) = _1]
),
space);
if (!r || first != last) // fail if we did not get a full match
return false;
c = rN;
return r;
}
template <typename Iterator>
static bool parse(Iterator first, Iterator last, std::complex<double>& c)
{
using boost::spirit::qi::double_;
using boost::spirit::qi::_1;
using boost::spirit::qi::phrase_parse;
using boost::spirit::ascii::space;
using boost::phoenix::ref;
double rN = 0.0;
double iN = 0.0;
bool r = phrase_parse(first, last,
(
'(' >> double_[ref(rN) = _1]
>> -(',' >> double_[ref(iN) = _1]) >> ')'
| double_[ref(rN) = _1]
),
space);
if (!r || first != last) // fail if we did not get a full match
return false;
c = std::complex<double>(rN, iN);
return r;
}
} // re: namespace cplusplus
} //re: namespace parsing
} //re: namespace bertini

View File

@@ -0,0 +1,182 @@
//This file is part of Bertini 2.
//
//bertini2/io/parsers.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.
//
//bertini2/io/parsing/number_rules.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 bertini2/io/parsing/number_rules.hpp. If not, see <http://www.gnu.org/licenses/>.
//
// Copyright(C) 2015 - 2017 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.
/**
\file bertini2/io/parsing/number_rules.hpp
\brief Provides the parsersing rules for numbers in bertini2.
*/
#pragma once
#include "bertini2/io/parsing/qi_files.hpp"
#include "bertini2/mpfr_complex.hpp"
#include "bertini2/num_traits.hpp"
BOOST_FUSION_ADAPT_ADT(
bertini::mpfr_complex,
(obj.real(), obj.real(val))
(obj.imag(), obj.imag(val)))
namespace bertini{
namespace parsing{
namespace qi = ::boost::spirit::qi;
namespace ascii = ::boost::spirit::ascii;
namespace rules{
/**
/brief Struct that holds the rules for parsing mpfr numbers
Use: Include this struct with the rest of your rules.
*/
template<typename Iterator>
struct LongNum
{
LongNum()
{
namespace phx = boost::phoenix;
using qi::_1;
using qi::_2;
using qi::_3;
using qi::_4;
using qi::_val;
using qi::eps;
using qi::lit;
using qi::char_;
using qi::omit;
using boost::spirit::lexeme;
using boost::spirit::as_string;
using boost::spirit::ascii::no_case;
number_string_.name("number_");
number_string_ =
long_number_string_
|
integer_string_;
integer_string_.name("integer_string_");
integer_string_ = eps[_val = std::string()] >>
-(qi::lit('-'))[_val += "-"] >>
number_with_no_point_ [_val += _1]
>> -exponent_notation_ [_val += _1];
long_number_string_.name("long_number_string_");
long_number_string_ = eps[_val = std::string()] >>
-(qi::lit('-'))[_val += "-"] >>
(
// 1. Read possible numbers before decimal, with possible negative
(number_with_digits_after_point_ [_val += _1]
|
number_with_digits_before_point_ [_val += _1] )
>> // reminder -- the - before the exponent_notation here means optional
-exponent_notation_ [_val+=_1]// Possible scientific notation, with possible negative in exponent.
);
number_with_digits_after_point_.name("number_with_digits_after_point_");
number_with_digits_after_point_ = eps[_val = std::string()]
>>
*(qi::char_(L'0',L'9')[_val += _1])
>>
qi::lit('.')[_val += "."] // find a decimal point
>>
+(qi::char_(L'0',L'9')[_val += _1]) // find at least one digit after the point
;
number_with_digits_before_point_.name("number_with_digits_before_point_");
number_with_digits_before_point_ = eps[_val = std::string()]
>>
+(qi::char_(L'0',L'9')[_val += _1])
>>
qi::lit('.')[_val += "."] // find a decimal point
>>
*(qi::char_(L'0',L'9')[_val += _1]) // find any number of digits after the point
;
number_with_no_point_.name("number_with_no_point_");
number_with_no_point_ = eps[_val = std::string()]
>>
(-(qi::lit('-')[_val += "-"]) // then an optional minus sign
>>
+(qi::char_(L'0',L'9'))[_val += _1])
;
exponent_notation_.name("exponent_notation_");
exponent_notation_ = eps[_val = std::string()]
>> ( // start what the rule actually does
(
qi::lit('e')[_val += "e"] // get an opening 'e'
|
qi::lit('E')[_val += "e"] // get an opening 'e'
)
>>
-(qi::lit('-')[_val += "-"]) // then an optional minus sign
>>
+(qi::char_(L'0',L'9')[_val += _1]) // then at least one number
); // finish the rule off
rational.name("long_rational");
rational =
(number_string_
|
(number_string_ >> char_('/') >> number_string_));
}
// these rules all produce strings which are fed into numbers.
qi::rule<Iterator, std::string()> number_string_, integer_string_, long_number_string_, number_with_digits_before_point_,
number_with_digits_after_point_, number_with_no_point_, exponent_notation_, rational;
}; //re: LongNum
} // namespace rules
}
}

View File

@@ -0,0 +1,53 @@
//This file is part of Bertini 2.
//
//bertini2/nag_algorithms/zero_dim_solve.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.
//
//bertini2/io/parsing/qi_files.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 bertini2/io/parsing/qi_files.hpp. If not, see <http://www.gnu.org/licenses/>.
//
// Copyright(C) 2015 - 2017 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.
/**
\file bertini2/io/parsing/qi_files.hpp
\brief Provides all the include files needed to develop a parsing file that uses boost qi.
*/
#pragma once
#define BOOST_SPIRIT_USE_PHOENIX_V3 1
#include <boost/fusion/adapted.hpp>
#include <boost/fusion/include/adapted.hpp>
#include <boost/spirit/include/qi.hpp>
#include <boost/phoenix.hpp>
#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/qi_core.hpp>
#include <boost/phoenix/core.hpp>
#include <boost/phoenix/operator.hpp>
#include <boost/fusion/include/std_pair.hpp>
#include <boost/phoenix/bind/bind_function.hpp>
#include <boost/phoenix/object/construct.hpp>
#include <boost/bind/bind.hpp>
#include <boost/fusion/adapted/adt/adapt_adt.hpp>
#include <boost/fusion/include/adapt_adt.hpp>
#include <boost/spirit/include/support_istream_iterator.hpp>

View File

@@ -0,0 +1,149 @@
//This file is part of Bertini 2.
//
//bertini2/io/parsers.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.
//
//bertini2/io/parsing/settings_parsers.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 bertini2/io/parsing/settings_parsers.hpp. If not, see <http://www.gnu.org/licenses/>.
//
// Copyright(C) 2015 - 2017 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.
/**
\file bertini2/io/parsing/settings_parsers.hpp
\brief Provides the parsers for settings in bertini2.
*/
#pragma once
#include "bertini2/detail/typelist.hpp"
#include "bertini2/io/parsing/settings_parsers/tracking.hpp"
#include "bertini2/io/parsing/settings_parsers/endgames.hpp"
#include "bertini2/io/parsing/settings_parsers/algorithm.hpp"
namespace bertini {
namespace parsing {
namespace classic {
/**
\brief Helper function to fill a single configuration struct by parsing a config input file.
\param config_str The comment-stripped configuration string from a Bertini classic input file.
\tparam ConfigT The config ConfigT type
\tparam RT Real number type
\returns The config struct filled with data from the input file.
*/
template<typename ConfigT>
ConfigT FillConfigStruct(std::string const& config_str)
{
std::string::const_iterator iter = config_str.begin();
std::string::const_iterator end = config_str.end();
ConfigT settings;
ConfigSettingParser<std::string::const_iterator, ConfigT> parser;
auto parse_success = phrase_parse(iter, end, parser,boost::spirit::ascii::space, settings);
if (!parse_success || iter!=end)
throw std::runtime_error("failed to parse into config struct from file");
return settings;
}
/**
\brief Base variadic parser for parsing many config structs at once.
A specialization for a typelist of configs appears below.
\tparam RT Real number type
\tparam Ts Configuration structures to be filled by the parser
*/
template<typename ...Ts>
struct ConfigParser
{
/**
The primary idea for filling a tuple using variadic templates comes from:
http://stackoverflow.com/questions/10014713/build-tuple-using-variadic-templates
\brief Reads in a comment-stripped, config portion of a Bertini classic input file. Parses the config settings and returns the structures passed into the template parameters with the relevant config settings.
\param config The string containing the comment-stripped config portion of the Bertini classic input file.
\return A tuple containing all the required config structures.
*/
static
std::tuple<Ts...> Parse(std::string const& config)
{
return std::make_tuple<Ts...>(FillConfigStruct<Ts>(config)...);
}
};
/**
\brief Specialization of ConfigParser for a single config struct
\tparam ConfigT The config ConfigT type
\tparam RT Real number type
*/
template<typename ConfigT>
struct ConfigParser <ConfigT>
{
/**
\brief Fill a single configuration struct by parsing a config input file.
\param config The comment-stripped configuration string from a Bertini classic input file.
\returns The config struct filled with data from the input file.
*/
static
ConfigT Parse(std::string const& config)
{
return FillConfigStruct<ConfigT>(config);
}
};
/**
\brief Specialization of ConfigParser for a typelist, returning a thing passed down from the base variadic case.
\tparam ConfigT The config ConfigT type
\tparam RT Real number type
*/
template<typename ...Ts>
struct ConfigParser<detail::TypeList<Ts...>>
{
static
auto Parse(std::string const& config)
{
return ConfigParser<Ts...>::Parse(config);
}
};
} // re: namespace classic
}// re: namespace parsing
}// re: namespace bertini

View File

@@ -0,0 +1,934 @@
//This file is part of Bertini 2.
//
//bertini2/io/parsing/settings_parsers/algorithm.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.
//
//bertini2/io/parsing/settings_parsers/algorithm.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 bertini2/io/parsing/settings_parsers/algorithm.hpp. If not, see <http://www.gnu.org/licenses/>.
//
// Copyright(C) 2015 - 2017 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.
/**
\file bertini2/io/parsing/settings_parsers/algorithm.hpp
\brief Provides the parsing rules for algorithm-related settings in bertini2.
*/
#pragma once
#include "bertini2/io/parsing/settings_parsers/base.hpp"
#include "bertini2/nag_algorithms/common/config.hpp"
namespace bertini {
namespace parsing {
namespace classic {
/**
*/
template<typename Iterator, typename Skipper>
struct ConfigSettingParser<Iterator, algorithm::TolerancesConfig, Skipper> : qi::grammar<Iterator, algorithm::TolerancesConfig(), Skipper>
{
using T = double;
ConfigSettingParser() : ConfigSettingParser::base_type(root_rule_, "config::TolerancesType")
{
namespace phx = boost::phoenix;
using qi::_1;
using qi::_2;
using qi::_3;
using qi::_4;
using qi::_val;
using qi::eps;
using qi::lit;
using qi::char_;
using qi::omit;
using boost::spirit::lexeme;
using boost::spirit::as_string;
using boost::spirit::ascii::no_case;
std::string newton_before_name = "tracktolbeforeeg";
std::string newton_during_name = "tracktolduringeg";
std::string final_tol_name = "finaltol";
std::string path_trunc_name = "pathtruncationthreshold";
root_rule_.name("config::Tolerances");
root_rule_ = ((newton_before_endgame_[phx::bind( [this](algorithm::TolerancesConfig & S, T l)
{
S.newton_before_endgame = l;
}, _val, _1 )]
^ newton_during_endgame_[phx::bind( [this](algorithm::TolerancesConfig & S, T num)
{
S.newton_during_endgame = num;
}, _val, _1 )]
^ final_tol_[phx::bind( [this](algorithm::TolerancesConfig & S, T num)
{
S.final_tolerance = num;
}, _val, _1 )]
^ path_trunc_threshold_[phx::bind( [this](algorithm::TolerancesConfig & S, T num)
{
S.path_truncation_threshold = num;
}, _val, _1 )])
>> -no_setting_)
| no_setting_;
all_names_ = (no_case[newton_before_name] >> ':') | (no_case[newton_during_name] >> ':')| (no_case[final_tol_name] >> ':')
| (no_case[path_trunc_name] >> ':');
newton_before_endgame_.name("newton_before_endgame_");
newton_before_endgame_ = *(char_ - all_names_) >> (no_case[newton_before_name] >> ':')
>> mpfr_rules.number_string_[phx::bind( [this](T & num, std::string str)
{
num = bertini::NumTraits<T>::FromString(str);
}, _val, _1 )] >> ';';
newton_during_endgame_.name("newton_during_endgame_");
newton_during_endgame_ = *(char_ - all_names_) >> (no_case[newton_during_name] >>':')
>> mpfr_rules.number_string_[phx::bind( [this](T & num, std::string str)
{
num = bertini::NumTraits<T>::FromString(str);
}, _val, _1 )] >> ';';
final_tol_.name("final_tol_");
final_tol_ = *(char_ - all_names_) >> (no_case[final_tol_name] >> ':')
>> mpfr_rules.number_string_[phx::bind( [this](T & num, std::string str)
{
num = bertini::NumTraits<T>::FromString(str);
}, _val, _1 )] >> ';';
path_trunc_threshold_.name("path_trunc_threshold_");
path_trunc_threshold_ = *(char_ - all_names_) >> (no_case[path_trunc_name] >> ':')
>> mpfr_rules.number_string_[phx::bind( [this](T & num, std::string str)
{
num = bertini::NumTraits<T>::FromString(str);
}, _val, _1 )] >> ';';
no_setting_.name("no_setting_");
no_setting_ = *(char_ - all_names_);
no_decl_.name("no_decl_");
no_decl_ = *(char_);
using phx::val;
using phx::construct;
using namespace qi::labels;
qi::on_error<qi::fail>
( root_rule_ ,
std::cout<<
val("config parser could not complete parsing. Expecting ")<<
_4<<
val(" here: ")<<
construct<std::string>(_3,_2)<<
std::endl
);
}
private:
qi::rule<Iterator, algorithm::TolerancesConfig(), ascii::space_type > root_rule_;
qi::rule<Iterator, T(), ascii::space_type > newton_before_endgame_, newton_during_endgame_,
final_tol_, path_trunc_threshold_;
qi::rule<Iterator, ascii::space_type, std::string()> no_decl_, no_setting_, all_names_;
rules::LongNum<Iterator> mpfr_rules;
}; //re: Tolerances
template<typename Iterator, typename ComplexT, typename Skipper>
struct ConfigSettingParser<Iterator, algorithm::ZeroDimConfig<ComplexT>, Skipper> : qi::grammar<Iterator, algorithm::ZeroDimConfig<ComplexT>(), Skipper>
{
ConfigSettingParser() : ConfigSettingParser::base_type(root_rule_, "algorithm::ZeroDimConfig")
{
namespace phx = boost::phoenix;
using qi::_1;
using qi::_2;
using qi::_3;
using qi::_4;
using qi::_val;
using qi::eps;
using qi::lit;
using qi::char_;
using qi::omit;
using boost::spirit::lexeme;
using boost::spirit::as_string;
using boost::spirit::ascii::no_case;
std::string init_prec_name = "initialprec";
std::string max_cross_resolve_name = "maxcrossedpathresolves";
std::string start_time_name = "starttime";
std::string endgame_boundary_name = "endgamebdry";
std::string target_time_name = "targettime";
std::string path_variable_name_name = "pathvarname";
root_rule_.name("config::ZeroDim");
root_rule_ = ((init_prec_[phx::bind( [this](algorithm::ZeroDimConfig<ComplexT> & S, int num)
{
S.initial_ambient_precision = num;
}, _val, _1 )]
^ path_variable_name_[phx::bind( [this](algorithm::ZeroDimConfig<ComplexT> & S, std::string omnom)
{
S.path_variable_name = omnom;
}, _val, _1 )]
^ max_cross_resolve_[phx::bind( [this](algorithm::ZeroDimConfig<ComplexT> & S, int num)
{
S.max_num_crossed_path_resolve_attempts = num;
}, _val, _1 )]
^ start_time_[phx::bind( [this](algorithm::ZeroDimConfig<ComplexT> & S, ComplexT num)
{
S.start_time = num;
}, _val, _1 )]
^ endgame_boundary_[phx::bind( [this](algorithm::ZeroDimConfig<ComplexT> & S, ComplexT num)
{
S.endgame_boundary = num;
}, _val, _1 )]
^ target_time_[phx::bind( [this](algorithm::ZeroDimConfig<ComplexT> & S, ComplexT num)
{
S.target_time = num;
}, _val, _1 )]
)
>> -no_setting_) | no_setting_;
all_names_ = (no_case[init_prec_name] >> ':') |
(no_case[target_time_name] >> ':') |
(no_case[path_variable_name_name] >> ':') |
(no_case[max_cross_resolve_name] >> ':') |
(no_case[start_time_name] >> ':') |
(no_case[endgame_boundary_name] >> ':')
;
auto str_to_ComplexT = [this](ComplexT & num, std::string str)
{
num = bertini::NumTraits<ComplexT>::FromString(str);
};
valid_variable_name_.name("valid_variable_name_");
valid_variable_name_ = +qi::alpha >> *(qi::alnum | qi::char_("[]_") );
path_variable_name_.name("path_variable_name_");
path_variable_name_ = *(char_ - all_names_) >> (no_case[path_variable_name_name] >> ':') >> valid_variable_name_ >> ';';
init_prec_.name("init_prec_");
init_prec_ = *(char_ - all_names_) >> (no_case[init_prec_name] >> ':') >> qi::int_[_val=_1] >> ';';
max_cross_resolve_.name("max_cross_resolve_");
max_cross_resolve_ = *(char_ - all_names_) >> (no_case[max_cross_resolve_name] >> ':') >> qi::int_[_val=_1] >> ';';
start_time_.name("start_time_");
start_time_ = *(char_ - all_names_) >> (no_case[start_time_name] >> ':')
>> mpfr_rules.number_string_[phx::bind( str_to_ComplexT, _val, _1 )] >> ';';
endgame_boundary_.name("endgame_boundary_");
endgame_boundary_ = *(char_ - all_names_) >> (no_case[endgame_boundary_name] >> ':')
>> mpfr_rules.number_string_[phx::bind( str_to_ComplexT, _val, _1 )] >> ';';
target_time_.name("target_time_");
target_time_ = *(char_ - all_names_) >> (no_case[target_time_name] >> ':')
>> mpfr_rules.number_string_[phx::bind( str_to_ComplexT, _val, _1 )] >> ';';
no_setting_.name("no_setting_");
no_setting_ = *(char_ - all_names_);
no_decl_.name("no_decl_");
no_decl_ = *(char_);
using phx::val;
using phx::construct;
using namespace qi::labels;
qi::on_error<qi::fail>
( root_rule_ ,
std::cout<<
val("config parser could not complete parsing. Expecting ")<<
_4<<
val(" here: ")<<
construct<std::string>(_3,_2)<<
std::endl
);
}
private:
qi::rule<Iterator, algorithm::ZeroDimConfig<ComplexT>(), ascii::space_type > root_rule_;
qi::rule<Iterator, ComplexT(), ascii::space_type > start_time_, target_time_, endgame_boundary_;
qi::rule<Iterator, int(), ascii::space_type > init_prec_, max_cross_resolve_;
qi::rule<Iterator, std::string(), ascii::space_type > valid_variable_name_, path_variable_name_;
qi::rule<Iterator, ascii::space_type, std::string()> no_decl_, no_setting_, all_names_;
rules::LongNum<Iterator> mpfr_rules;
}; //re: ZeroDim
template<typename Iterator, typename Skipper>
struct ConfigSettingParser<Iterator, algorithm::MidPathConfig, Skipper> : qi::grammar<Iterator, algorithm::MidPathConfig(), Skipper>
{
using T = double;
ConfigSettingParser() : ConfigSettingParser::base_type(root_rule_, "config::MidPath")
{
namespace phx = boost::phoenix;
using qi::_1;
using qi::_2;
using qi::_3;
using qi::_4;
using qi::_val;
using qi::eps;
using qi::lit;
using qi::char_;
using qi::omit;
using boost::spirit::lexeme;
using boost::spirit::as_string;
using boost::spirit::ascii::no_case;
std::string same_point_tol_name = "midpathtol";
root_rule_.name("config::MidPath");
root_rule_ = ((same_point_tol_[phx::bind( [this](algorithm::MidPathConfig & S, T num)
{
S.same_point_tolerance = num;
}, _val, _1 )]
)
>> -no_setting_) | no_setting_;
all_names_ = (no_case[same_point_tol_name] >> ':');
auto str_to_T = [this](T & num, std::string str)
{
num = bertini::NumTraits<T>::FromString(str);
};
same_point_tol_.name("same_point_tol_");
same_point_tol_ = *(char_ - all_names_) >> (no_case[same_point_tol_name] >> ':')
>> mpfr_rules.number_string_[phx::bind( str_to_T, _val, _1 )] >> ';';
no_setting_.name("no_setting_");
no_setting_ = *(char_ - all_names_);
no_decl_.name("no_decl_");
no_decl_ = *(char_);
using phx::val;
using phx::construct;
using namespace qi::labels;
qi::on_error<qi::fail>
( root_rule_ ,
std::cout<<
val("config parser could not complete parsing. Expecting ")<<
_4<<
val(" here: ")<<
construct<std::string>(_3,_2)<<
std::endl
);
}
private:
qi::rule<Iterator, algorithm::MidPathConfig(), ascii::space_type > root_rule_;
qi::rule<Iterator, T(), ascii::space_type > same_point_tol_;
qi::rule<Iterator, ascii::space_type, std::string()> no_decl_, no_setting_, all_names_;
rules::LongNum<Iterator> mpfr_rules;
}; //re: MidPath
template<typename Iterator, typename Skipper>
struct ConfigSettingParser<Iterator, algorithm::AutoRetrackConfig, Skipper> : qi::grammar<Iterator, algorithm::AutoRetrackConfig(), Skipper>
{
using T = double;
ConfigSettingParser() : ConfigSettingParser::base_type(root_rule_, "config::AutoRetrack")
{
namespace phx = boost::phoenix;
using qi::_1;
using qi::_2;
using qi::_3;
using qi::_4;
using qi::_val;
using qi::eps;
using qi::lit;
using qi::char_;
using qi::omit;
using boost::spirit::lexeme;
using boost::spirit::as_string;
using boost::spirit::ascii::no_case;
std::string decrease_factor_name = "retracktolfactor";
root_rule_.name("config::AutoRetrack");
root_rule_ = ((decrease_factor[phx::bind( [this](algorithm::AutoRetrackConfig & S, T num)
{
S.midpath_decrease_tolerance_factor = num;
}, _val, _1 )]
)
>> -no_setting_) | no_setting_;
all_names_ = (no_case[decrease_factor_name] >> ':');
auto str_to_T = [this](T & num, std::string str)
{
num = bertini::NumTraits<T>::FromString(str);
};
decrease_factor.name("decrease_factor");
decrease_factor = *(char_ - all_names_) >> (no_case[decrease_factor_name] >> ':')
>> mpfr_rules.number_string_[phx::bind( str_to_T, _val, _1 )] >> ';';
no_setting_.name("no_setting_");
no_setting_ = *(char_ - all_names_);
no_decl_.name("no_decl_");
no_decl_ = *(char_);
using phx::val;
using phx::construct;
using namespace qi::labels;
qi::on_error<qi::fail>
( root_rule_ ,
std::cout<<
val("config parser could not complete parsing. Expecting ")<<
_4<<
val(" here: ")<<
construct<std::string>(_3,_2)<<
std::endl
);
}
private:
qi::rule<Iterator, algorithm::AutoRetrackConfig(), ascii::space_type > root_rule_;
qi::rule<Iterator, T(), ascii::space_type > decrease_factor;
qi::rule<Iterator, ascii::space_type, std::string()> no_decl_, no_setting_, all_names_;
rules::LongNum<Iterator> mpfr_rules;
}; //re: AutoRetrack
template<typename Iterator, typename Skipper>
struct ConfigSettingParser<Iterator, algorithm::SharpeningConfig, Skipper> : qi::grammar<Iterator, algorithm::SharpeningConfig(), Skipper>
{
using T = double;
ConfigSettingParser() : ConfigSettingParser::base_type(root_rule_, "algorithm::config::Sharpening")
{
namespace phx = boost::phoenix;
using qi::_1;
using qi::_2;
using qi::_3;
using qi::_4;
using qi::_val;
using qi::eps;
using qi::lit;
using qi::char_;
using qi::omit;
using boost::spirit::lexeme;
using boost::spirit::as_string;
using boost::spirit::ascii::no_case;
std::string sharpen_digits_name = "sharpendigits";
std::string func_res_tol_name = "functiontolerance";
std::string ratio_tol_name = "ratiotolerance";
root_rule_.name("config::Sharpening");
root_rule_ = ((sharpen_digits_[phx::bind( [this](algorithm::SharpeningConfig & S, unsigned num)
{
S.sharpendigits = num;
}, _val, _1 )]
^ func_res_tol_[phx::bind( [this](algorithm::SharpeningConfig & S, T num)
{
S.function_residual_tolerance = num;
}, _val, _1 )]
^ ratio_tol_[phx::bind( [this](algorithm::SharpeningConfig & S, T num)
{
S.ratio_tolerance = num;
}, _val, _1 )]
)
>> -no_setting_) | no_setting_;
all_names_ = (no_case[sharpen_digits_name] >> ':') |
(no_case[func_res_tol_name] >> ':') |
(no_case[ratio_tol_name] >> ':')
;
auto str_to_T = [this](T & num, std::string str)
{
num = bertini::NumTraits<T>::FromString(str);
};
func_res_tol_.name("func_res_tol_");
func_res_tol_ = *(char_ - all_names_) >> (no_case[func_res_tol_name] >> ':')
>> mpfr_rules.number_string_[phx::bind( str_to_T, _val, _1 )] >> ';';
ratio_tol_.name("ratio_tol_");
ratio_tol_ = *(char_ - all_names_) >> (no_case[ratio_tol_name] >> ':')
>> mpfr_rules.number_string_[phx::bind( str_to_T, _val, _1 )] >> ';';
sharpen_digits_.name("sharpen_digits_");
sharpen_digits_ = *(char_ - all_names_) >> (no_case[sharpen_digits_name] >> ':') >> qi::uint_[_val=_1] >> ';';
no_setting_.name("no_setting_");
no_setting_ = *(char_ - all_names_);
no_decl_.name("no_decl_");
no_decl_ = *(char_);
using phx::val;
using phx::construct;
using namespace qi::labels;
qi::on_error<qi::fail>
( root_rule_ ,
std::cout<<
val("config parser could not complete parsing. Expecting ")<<
_4<<
val(" here: ")<<
construct<std::string>(_3,_2)<<
std::endl
);
}
private:
qi::rule<Iterator, algorithm::SharpeningConfig(), ascii::space_type > root_rule_;
qi::rule<Iterator, T(), ascii::space_type > func_res_tol_, ratio_tol_;
qi::rule<Iterator, unsigned int(), ascii::space_type > sharpen_digits_;
qi::rule<Iterator, ascii::space_type, std::string()> no_decl_, no_setting_, all_names_;
rules::LongNum<Iterator> mpfr_rules;
}; //re: Sharpening
template<typename Iterator, typename Skipper>
struct ConfigSettingParser<Iterator, algorithm::RegenerationConfig, Skipper> : qi::grammar<Iterator, algorithm::RegenerationConfig(), Skipper>
{
using T = double;
ConfigSettingParser() : ConfigSettingParser::base_type(root_rule_, "algorithm::config::Regeneration")
{
namespace phx = boost::phoenix;
using qi::_1;
using qi::_2;
using qi::_3;
using qi::_4;
using qi::_val;
using qi::eps;
using qi::lit;
using qi::char_;
using qi::omit;
using boost::spirit::lexeme;
using boost::spirit::as_string;
using boost::spirit::ascii::no_case;
std::string regen_remove_inf_name = "regenremoveinf";
std::string slice_before_name = "slicetolbeforeeg";
std::string slice_during_name = "slicetolduringeg";
std::string slice_final_name = "slicefinaltol";
std::string higher_dim_check_name = "regenhigherdimtest";
std::string start_level_name = "regenstartlevel";
root_rule_.name("config::Regeneration");
root_rule_ = ((regen_remove_inf_[phx::bind( [this](algorithm::RegenerationConfig & S, int num)
{
S.remove_infinite_endpoints = static_cast<bool>(num);
}, _val, _1 )]
^ higher_dim_check_[phx::bind( [this](algorithm::RegenerationConfig & S, int num)
{
S.higher_dimension_check = static_cast<bool>(num);
}, _val, _1 )]
^ start_level_[phx::bind( [this](algorithm::RegenerationConfig & S, int num)
{
S.start_level = num;
}, _val, _1 )]
^ slice_before_[phx::bind( [this](algorithm::RegenerationConfig & S, T num)
{
S.newton_before_endgame = num;
}, _val, _1 )]
^ slice_during_[phx::bind( [this](algorithm::RegenerationConfig & S, T num)
{
S.newton_during_endgame = num;
}, _val, _1 )]
^ slice_final_[phx::bind( [this](algorithm::RegenerationConfig & S, T num)
{
S.final_tolerance = num;
}, _val, _1 )]
)
>> -no_setting_) | no_setting_;
all_names_ = (no_case[regen_remove_inf_name] >> ':') |
(no_case[higher_dim_check_name] >> ':') |
(no_case[start_level_name] >> ':') |
(no_case[slice_before_name] >> ':') |
(no_case[slice_during_name] >> ':') |
(no_case[slice_final_name] >> ':')
;
auto str_to_T = [this](T & num, std::string str)
{
num = bertini::NumTraits<T>::FromString(str);
};
higher_dim_check_.name("higher_dim_check_");
higher_dim_check_ = *(char_ - all_names_) >> (no_case[higher_dim_check_name] >> ':') >> qi::int_[_val=_1] >> ';';
start_level_.name("start_level_");
start_level_ = *(char_ - all_names_) >> (no_case[start_level_name] >> ':') >> qi::int_[_val=_1] >> ';';
regen_remove_inf_.name("regen_remove_inf_");
regen_remove_inf_ = *(char_ - all_names_) >> (no_case[regen_remove_inf_name] >> ':') >> qi::int_[_val=_1] >> ';';
slice_before_.name("slice_before_");
slice_before_ = *(char_ - all_names_) >> (no_case[slice_before_name] >> ':')
>> mpfr_rules.number_string_[phx::bind( str_to_T, _val, _1 )] >> ';';
slice_during_.name("slice_during_");
slice_during_ = *(char_ - all_names_) >> (no_case[slice_during_name] >> ':')
>> mpfr_rules.number_string_[phx::bind( str_to_T, _val, _1 )] >> ';';
slice_final_.name("slice_final_");
slice_final_ = *(char_ - all_names_) >> (no_case[slice_final_name] >> ':')
>> mpfr_rules.number_string_[phx::bind( str_to_T, _val, _1 )] >> ';';
no_setting_.name("no_setting_");
no_setting_ = *(char_ - all_names_);
no_decl_.name("no_decl_");
no_decl_ = *(char_);
using phx::val;
using phx::construct;
using namespace qi::labels;
qi::on_error<qi::fail>
( root_rule_ ,
std::cout<<
val("config parser could not complete parsing. Expecting ")<<
_4<<
val(" here: ")<<
construct<std::string>(_3,_2)<<
std::endl
);
}
private:
qi::rule<Iterator, algorithm::RegenerationConfig(), ascii::space_type > root_rule_;
qi::rule<Iterator, T(), ascii::space_type > slice_before_, slice_during_, slice_final_;
qi::rule<Iterator, int(), ascii::space_type > regen_remove_inf_, start_level_, higher_dim_check_;
qi::rule<Iterator, ascii::space_type, std::string()> no_decl_, no_setting_, all_names_;
rules::LongNum<Iterator> mpfr_rules;
}; //re: Regeneration
template<typename Iterator, typename Skipper>
struct ConfigSettingParser<Iterator, algorithm::PostProcessingConfig, Skipper> : qi::grammar<Iterator, algorithm::PostProcessingConfig(), Skipper>
{
using T = double;
ConfigSettingParser() : ConfigSettingParser::base_type(root_rule_, "algorithm::PostProcessingConfig")
{
namespace phx = boost::phoenix;
using qi::_1;
using qi::_2;
using qi::_3;
using qi::_4;
using qi::_val;
using qi::eps;
using qi::lit;
using qi::char_;
using qi::omit;
using boost::spirit::lexeme;
using boost::spirit::as_string;
using boost::spirit::ascii::no_case;
std::string real_thresh_name = "imagthreshold";
std::string endpoint_finite_name = "endpointfinitethreshold";
std::string same_point_name = "endpointsamethreshold";
root_rule_.name("config::PostProcessing");
root_rule_ = ((real_threshold_[phx::bind( [this](algorithm::PostProcessingConfig & S, T num)
{
S.real_threshold = num;
}, _val, _1 )]
^ endpoint_finite_[phx::bind( [this](algorithm::PostProcessingConfig & S, T num)
{
S.endpoint_finite_threshold = num;
}, _val, _1 )]
^ same_point_[phx::bind( [this](algorithm::PostProcessingConfig & S, T num)
{
S.same_point_tolerance = num;
}, _val, _1 )]
)
>> -no_setting_) | no_setting_;
all_names_ = (no_case[real_thresh_name] >> ':') |
(no_case[endpoint_finite_name] >> ':') |
(no_case[same_point_name] >> ':')
;
auto str_to_T = [this](T & num, std::string str)
{
num = bertini::NumTraits<T>::FromString(str);
};
real_threshold_.name("real_thresh_");
real_threshold_ = *(char_ - all_names_) >> (no_case[real_thresh_name] >> ':')
>> mpfr_rules.number_string_[phx::bind( str_to_T, _val, _1 )] >> ';';
endpoint_finite_.name("endpoint_finite_");
endpoint_finite_ = *(char_ - all_names_) >> (no_case[endpoint_finite_name] >> ':')
>> mpfr_rules.number_string_[phx::bind( str_to_T, _val, _1 )] >> ';';
same_point_.name("same_point_");
same_point_ = *(char_ - all_names_) >> (no_case[same_point_name] >> ':')
>> mpfr_rules.number_string_[phx::bind( str_to_T, _val, _1 )] >> ';';
no_setting_.name("no_setting_");
no_setting_ = *(char_ - all_names_);
no_decl_.name("no_decl_");
no_decl_ = *(char_);
using phx::val;
using phx::construct;
using namespace qi::labels;
qi::on_error<qi::fail>
( root_rule_ ,
std::cout<<
val("config parser could not complete parsing. Expecting ")<<
_4<<
val(" here: ")<<
construct<std::string>(_3,_2)<<
std::endl
);
}
private:
qi::rule<Iterator, algorithm::PostProcessingConfig(), ascii::space_type > root_rule_;
qi::rule<Iterator, T(), ascii::space_type > real_threshold_, endpoint_finite_, same_point_;
qi::rule<Iterator, ascii::space_type, std::string()> no_decl_, no_setting_, all_names_;
rules::LongNum<Iterator> mpfr_rules;
}; //re: PostProcessing
template<typename Iterator, typename Skipper> //boost::spirit::unused_type
struct ConfigSettingParser<Iterator, algorithm::classic::AlgoChoice, Skipper> : qi::grammar<Iterator, algorithm::classic::AlgoChoice(), Skipper>
{
using T = double;
ConfigSettingParser() : ConfigSettingParser::base_type(root_rule_, "config::classic::AlgoChoice")
{
namespace phx = boost::phoenix;
using qi::_1;
using qi::_2;
using qi::_3;
using qi::_4;
using qi::_val;
using qi::eps;
using qi::lit;
using qi::char_;
using qi::omit;
using boost::spirit::lexeme;
using boost::spirit::as_string;
using boost::spirit::ascii::no_case;
tracktype_.add("-4", algorithm::classic::AlgoChoice::EvalFunctions);
tracktype_.add("-3", algorithm::classic::AlgoChoice::EvalFunctionJacobian);
tracktype_.add("-2", algorithm::classic::AlgoChoice::NewtonIteration);
tracktype_.add("-1", algorithm::classic::AlgoChoice::NewtonIterationCondNum);
tracktype_.add("0", algorithm::classic::AlgoChoice::ZeroDim);
tracktype_.add("1", algorithm::classic::AlgoChoice::NID);
tracktype_.add("2", algorithm::classic::AlgoChoice::SampleComponent);
tracktype_.add("3", algorithm::classic::AlgoChoice::MembershipTest);
tracktype_.add("4", algorithm::classic::AlgoChoice::ExtractWitnessSet);
tracktype_.add("5", algorithm::classic::AlgoChoice::WitnessSetProjection);
tracktype_.add("6", algorithm::classic::AlgoChoice::IsosingularStab);
std::string setting_name = "tracktype";
root_rule_.name("config::classic::AlgoChoice");
root_rule_ = config_name_[_val = _1] >> -no_setting_
| no_setting_[_val = algorithm::classic::AlgoChoice::ZeroDim];
config_name_.name("tracktype_");
config_name_ = *(char_ - (no_case[setting_name] >> ':')) >> (no_case[setting_name] >> ':') >> tracktype_[_val = _1] >> ';';
no_setting_.name("no_setting_");
no_setting_ = *(char_ - no_case[setting_name]);
no_decl_.name("no_decl_");
no_decl_ = *(char_);
using phx::val;
using phx::construct;
using namespace qi::labels;
qi::on_error<qi::fail>
( root_rule_ ,
std::cout<<
val("config parser could not complete parsing. Expecting ")<<
_4<<
val(" here: ")<<
construct<std::string>(_3,_2)<<
std::endl
);
}
private:
qi::rule<Iterator, algorithm::classic::AlgoChoice(), ascii::space_type > root_rule_, config_name_;
qi::rule<Iterator, ascii::space_type, std::string()> no_decl_, no_setting_;
qi::symbols<char,algorithm::classic::AlgoChoice> tracktype_;
}; //re: Meta
} // re: namespace classic
}// re: namespace parsing
}// re: namespace bertini

View File

@@ -0,0 +1,59 @@
//This file is part of Bertini 2.
//
//bertini2/io/parsing/settings_parsers/base.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.
//
//bertini2/io/parsing/settings_parsers/base.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 bertini2/io/parsing/settings_parsers/base.hpp. If not, see <http://www.gnu.org/licenses/>.
//
// Copyright(C) 2015 - 2017 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.
/**
\file bertini2/io/parsing/settings_parsers/base.hpp
\brief Provides the base type for config settings parsers
*/
#pragma once
#include "bertini2/io/parsing/qi_files.hpp"
#include "bertini2/io/parsing/number_rules.hpp"
namespace bertini {
namespace parsing {
namespace classic {
namespace qi = ::boost::spirit::qi;
namespace ascii = ::boost::spirit::ascii;
/**
Qi Parser object for parsing config settings This ensures we can provide backwards compatibility with Bertini Classic input files.
This is a base case template, which we specialize elsewhere
*/
template<typename Iterator, typename Structure, typename Skipper = ascii::space_type> //boost::spirit::unused_type
struct ConfigSettingParser : qi::grammar<Iterator, Structure(), Skipper>
{
};
} // re: namespace classic
}// re: namespace parsing
}// re: namespace bertini

View File

@@ -0,0 +1,533 @@
//This file is part of Bertini 2.
//
//bertini2/io/parsing/settings_parsers/endgames.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.
//
//bertini2/io/parsing/settings_parsers/endgames.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 bertini2/io/parsing/settings_parsers/endgames.hpp. If not, see <http://www.gnu.org/licenses/>.
//
// Copyright(C) 2015 - 2017 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.
/**
\file bertini2/io/parsing/settings_parsers/endgames.hpp
\brief Provides the parsing rules for endgames-related settings in bertini2.
*/
#pragma once
#include "bertini2/io/parsing/settings_parsers/base.hpp"
#include "bertini2/endgames/config.hpp"
namespace bertini {
namespace parsing {
namespace classic {
/**
*/
template<typename Iterator, typename Skipper> //boost::spirit::unused_type
struct ConfigSettingParser<Iterator, bertini::endgame::SecurityConfig, Skipper> : qi::grammar<Iterator, bertini::endgame::SecurityConfig(), Skipper>
{
using T = double;
ConfigSettingParser() : ConfigSettingParser::base_type(root_rule_, "SecurityConfig")
{
namespace phx = boost::phoenix;
using qi::_1;
using qi::_2;
using qi::_3;
using qi::_4;
using qi::_val;
using qi::eps;
using qi::lit;
using qi::char_;
using qi::omit;
using boost::spirit::lexeme;
using boost::spirit::as_string;
using boost::spirit::ascii::no_case;
std::string level_name = "securitylevel";
std::string maxnorm_name = "securitymaxnorm";
root_rule_.name("config::Security");
root_rule_ = ((security_level_[phx::bind( [this](bertini::endgame::SecurityConfig & S, int l)
{
S.level = l;
}, _val, _1 )]
^ security_max_norm_[phx::bind( [this](bertini::endgame::SecurityConfig & S, T norm)
{
S.max_norm = norm;
}, _val, _1 )])
>> -no_setting_) | no_setting_;
all_names_ = (no_case[level_name] >> ':') | (no_case[maxnorm_name] >> ':');
security_level_.name("security_level_");
security_level_ = *(char_ - all_names_) >> (no_case[level_name] >> ':') >> qi::int_[_val = _1] >> ';';
security_max_norm_.name("security_max_norm_");
security_max_norm_ = *(char_ - all_names_) >> (no_case[maxnorm_name] >> ':')
>> mpfr_rules.number_string_[phx::bind( [this](T & num, std::string str)
{
num = bertini::NumTraits<T>::FromString(str);
}, _val, _1 )] >> ';';
no_setting_.name("no_setting_");
no_setting_ = *(char_ - all_names_);
no_decl_.name("no_decl_");
no_decl_ = *(char_);
using phx::val;
using phx::construct;
using namespace qi::labels;
qi::on_error<qi::fail>
( root_rule_ ,
std::cout<<
val("config parser could not complete parsing. Expecting ")<<
_4<<
val(" here: ")<<
construct<std::string>(_3,_2)<<
std::endl
);
}
private:
qi::rule<Iterator, bertini::endgame::SecurityConfig(), ascii::space_type > root_rule_;
qi::rule<Iterator, int(), ascii::space_type > security_level_;
qi::rule<Iterator, T(), ascii::space_type > security_max_norm_;
qi::rule<Iterator, ascii::space_type, std::string()> no_decl_, no_setting_, all_names_;
rules::LongNum<Iterator> mpfr_rules;
}; //re: SecurityParser
/**
*/
template<typename Iterator, typename Skipper> //boost::spirit::unused_type
struct ConfigSettingParser<Iterator, bertini::endgame::EndgameConfig, Skipper> : qi::grammar<Iterator, bertini::endgame::EndgameConfig(), Skipper>
{
using T = double;
using R = mpq_rational;
ConfigSettingParser() : ConfigSettingParser::base_type(root_rule_, "EndgameConfig")
{
namespace phx = boost::phoenix;
using qi::_1;
using qi::_2;
using qi::_3;
using qi::_4;
using qi::_val;
using qi::eps;
using qi::lit;
using qi::char_;
using qi::omit;
using boost::spirit::lexeme;
using boost::spirit::as_string;
using boost::spirit::ascii::no_case;
std::string samplefactor_name = "samplefactor";
std::string numpoints_name = "numsamplepoints";
std::string mintrack_name = "nbhdradius";
root_rule_.name("config::Endgame");
root_rule_ = ((sample_factor_[phx::bind( [this](bertini::endgame::EndgameConfig & S, R num)
{
S.sample_factor = num;
}, _val, _1 )]
^ min_track_[phx::bind( [this](bertini::endgame::EndgameConfig & S, T num)
{
S.min_track_time = num;
}, _val, _1 )]
^ num_sample_[phx::bind( [this](bertini::endgame::EndgameConfig & S, unsigned num)
{
S.num_sample_points = num;
}, _val, _1 )])
>> -no_setting_)
| no_setting_;
all_names_ = (no_case[samplefactor_name] >> ':') | (no_case[numpoints_name] >> ':')| (no_case[mintrack_name] >> ':');
sample_factor_.name("sample_factor_");
sample_factor_ = *(char_ - all_names_) >> (no_case[samplefactor_name] >> ':')
>> mpfr_rules.rational[phx::bind( [this](R & num, std::string str)
{
num = bertini::NumTraits<double>::FromString(str);
}, _val, _1 )] >> ';';
min_track_.name("min_track_");
min_track_ = *(char_ - all_names_) >> (no_case[mintrack_name] >> ':')
>> mpfr_rules.number_string_[phx::bind( [this](T & num, std::string str)
{
num = bertini::NumTraits<T>::FromString(str);
}, _val, _1 )] >> ';';
num_sample_.name("num_sample_");
num_sample_ = *(char_ - all_names_) >> (no_case[numpoints_name] >> ':')
>> qi::uint_[_val=_1] >> ';';
no_setting_.name("no_setting_");
no_setting_ = *(char_ - all_names_);
no_decl_.name("no_decl_");
no_decl_ = *(char_);
using phx::val;
using phx::construct;
using namespace qi::labels;
qi::on_error<qi::fail>
( root_rule_ ,
std::cout<<
val("config parser could not complete parsing. Expecting ")<<
_4<<
val(" here: ")<<
construct<std::string>(_3,_2)<<
std::endl
);
}
private:
qi::rule<Iterator, bertini::endgame::EndgameConfig(), ascii::space_type > root_rule_;
qi::rule<Iterator, R(), ascii::space_type > sample_factor_;
qi::rule<Iterator, T(), ascii::space_type > min_track_;
qi::rule<Iterator, unsigned int(), ascii::space_type > num_sample_;
qi::rule<Iterator, ascii::space_type, std::string()> no_decl_, no_setting_, all_names_;
rules::LongNum<Iterator> mpfr_rules;
}; //re: EndgameParser
/**
*/
template<typename Iterator, typename Skipper> //boost::spirit::unused_type
struct ConfigSettingParser<Iterator, bertini::endgame::PowerSeriesConfig, Skipper> : qi::grammar<Iterator, bertini::endgame::PowerSeriesConfig(), Skipper>
{
using T = double;
ConfigSettingParser() : ConfigSettingParser::base_type(root_rule_, "bertini::endgame::PowerSeriesConfigType")
{
namespace phx = boost::phoenix;
using qi::_1;
using qi::_2;
using qi::_3;
using qi::_4;
using qi::_val;
using qi::eps;
using qi::lit;
using qi::char_;
using qi::omit;
using boost::spirit::lexeme;
using boost::spirit::as_string;
using boost::spirit::ascii::no_case;
std::string maxcycle_name = "maxcyclenum";
root_rule_.name("bertini::endgame::PowerSeriesConfig");
root_rule_ = (max_cycle_[phx::bind( [this](bertini::endgame::PowerSeriesConfig & S, unsigned num)
{
S.max_cycle_number = num;
}, _val, _1 )]
>> -no_setting_)
| no_setting_;
all_names_ = eps >> (no_case[maxcycle_name] >> ':');
max_cycle_.name("max_cycle_");
max_cycle_ = *(char_ - all_names_) >> (no_case[maxcycle_name] >> ':') >> qi::uint_[_val=_1] >> ';';
no_setting_.name("no_setting_");
no_setting_ = *(char_ - all_names_);
no_decl_.name("no_decl_");
no_decl_ = *(char_);
using phx::val;
using phx::construct;
using namespace qi::labels;
qi::on_error<qi::fail>
( root_rule_ ,
std::cout<<
val("config parser could not complete parsing. Expecting ")<<
_4<<
val(" here: ")<<
construct<std::string>(_3,_2)<<
std::endl
);
}
private:
qi::rule<Iterator, bertini::endgame::PowerSeriesConfig(), Skipper> root_rule_;
qi::rule<Iterator, unsigned int(), ascii::space_type > max_cycle_;
qi::rule<Iterator, ascii::space_type, std::string()> no_decl_, no_setting_, all_names_;
}; //re: PowerSeriesParser
/**
*/
template<typename Iterator, typename Skipper> //boost::spirit::unused_type
struct ConfigSettingParser<Iterator, bertini::endgame::CauchyConfig, Skipper> : qi::grammar<Iterator, bertini::endgame::CauchyConfig(), Skipper>
{
using T = double;
ConfigSettingParser() : ConfigSettingParser::base_type(root_rule_, "bertini::endgame::CauchyConfig")
{
namespace phx = boost::phoenix;
using qi::_1;
using qi::_2;
using qi::_3;
using qi::_4;
using qi::_val;
using qi::eps;
using qi::lit;
using qi::char_;
using qi::omit;
using boost::spirit::lexeme;
using boost::spirit::as_string;
using boost::spirit::ascii::no_case;
std::string cyclecutoff_name = "cycletimecutoff";
std::string ratiocutoff_name = "ratiotimecutoff";
root_rule_.name("config::Cauchy");
root_rule_ = ((cycle_cutoff_[phx::bind( [this](bertini::endgame::CauchyConfig & S, T num)
{
S.cycle_cutoff_time = num;
}, _val, _1 )]
^ ratio_cutoff_[phx::bind( [this](bertini::endgame::CauchyConfig & S, T num)
{
S.ratio_cutoff_time = num;
}, _val, _1 )])
>> -no_setting_) | no_setting_;
all_names_ = (no_case[cyclecutoff_name] >> ':') | (no_case[ratiocutoff_name] >> ':');
cycle_cutoff_.name("cycle_cutoff_");
cycle_cutoff_ = *(char_ - all_names_) >> (no_case[cyclecutoff_name] >> ':')
>> mpfr_rules.number_string_[phx::bind( [this](T & num, std::string str)
{
num = bertini::NumTraits<T>::FromString(str);
}, _val, _1 )] >> ';';
ratio_cutoff_.name("ratio_cutoff_");
ratio_cutoff_ = *(char_ - all_names_) >> (no_case[ratiocutoff_name] >> ':')
>> mpfr_rules.number_string_[phx::bind( [this](T & num, std::string str)
{
num = bertini::NumTraits<T>::FromString(str);
}, _val, _1 )] >> ';';
no_setting_.name("no_setting_");
no_setting_ = *(char_ - all_names_);
no_decl_.name("no_decl_");
no_decl_ = *(char_);
using phx::val;
using phx::construct;
using namespace qi::labels;
qi::on_error<qi::fail>
( root_rule_ ,
std::cout<<
val("config parser could not complete parsing. Expecting ")<<
_4<<
val(" here: ")<<
construct<std::string>(_3,_2)<<
std::endl
);
}
private:
qi::rule<Iterator, bertini::endgame::CauchyConfig(), ascii::space_type > root_rule_;
qi::rule<Iterator, T(), ascii::space_type > cycle_cutoff_, ratio_cutoff_;
qi::rule<Iterator, ascii::space_type, std::string()> no_decl_, no_setting_, all_names_;
rules::LongNum<Iterator> mpfr_rules;
}; //re: CauchyParser
template<typename Iterator, typename Skipper> //boost::spirit::unused_type
struct ConfigSettingParser<Iterator, bertini::endgame::TrackBackConfig, Skipper> : qi::grammar<Iterator, bertini::endgame::TrackBackConfig(), Skipper>
{
using T = double;
ConfigSettingParser() : ConfigSettingParser::base_type(root_rule_, "bertini::endgame::TrackBackConfig")
{
namespace phx = boost::phoenix;
using qi::_1;
using qi::_2;
using qi::_3;
using qi::_4;
using qi::_val;
using qi::eps;
using qi::lit;
using qi::char_;
using qi::omit;
using boost::spirit::lexeme;
using boost::spirit::as_string;
using boost::spirit::ascii::no_case;
std::string min_cycle_name = "mincycletrackback";
std::string junk_removal_name = "junkremovaltrackback";
std::string maxdepth_name = "maxldtdepth";
root_rule_.name("bertini::endgame::TrackBackConfig");
root_rule_ = root_rule_ = ((min_cycle_[phx::bind( [this](bertini::endgame::TrackBackConfig & S, unsigned num)
{
S.minimum_cycle = num;
}, _val, _1 )]
^ junk_removal_[phx::bind( [this](bertini::endgame::TrackBackConfig & S, int num)
{
S.junk_removal_test = static_cast<bool>(num);
}, _val, _1 )]
^ max_depth_[phx::bind( [this](bertini::endgame::TrackBackConfig & S, unsigned num)
{
S.max_depth_LDT = num;
}, _val, _1 )]
)
>> -no_setting_) | no_setting_;
all_names_ = eps >> (no_case[min_cycle_name] >> ':') |
(no_case[junk_removal_name] >> ':') |
(no_case[maxdepth_name] >> ':');
min_cycle_.name("min_cycle_");
min_cycle_ = *(char_ - all_names_) >> (no_case[min_cycle_name] >> ':') >> qi::uint_[_val=_1] >> ';';
junk_removal_.name("junk_removal_");
junk_removal_ = *(char_ - all_names_) >> (no_case[junk_removal_name] >> ':') >> qi::int_[_val=_1] >> ';';
max_depth_.name("max_depth_");
max_depth_ = *(char_ - all_names_) >> (no_case[maxdepth_name] >> ':') >> qi::uint_[_val=_1] >> ';';
no_setting_.name("no_setting_");
no_setting_ = *(char_ - all_names_);
no_decl_.name("no_decl_");
no_decl_ = *(char_);
using phx::val;
using phx::construct;
using namespace qi::labels;
qi::on_error<qi::fail>
( root_rule_ ,
std::cout<<
val("config parser could not complete parsing. Expecting ")<<
_4<<
val(" here: ")<<
construct<std::string>(_3,_2)<<
std::endl
);
}
private:
qi::rule<Iterator, bertini::endgame::TrackBackConfig(), Skipper> root_rule_;
qi::rule<Iterator, unsigned int(), ascii::space_type > min_cycle_, max_depth_;
qi::rule<Iterator, int(), ascii::space_type > junk_removal_;
qi::rule<Iterator, ascii::space_type, std::string()> no_decl_, no_setting_, all_names_;
}; //re: TrackBackParser
} // re: namespace classic
}// re: namespace parsing
}// re: namespace bertini

View File

@@ -0,0 +1,705 @@
//This file is part of Bertini 2.
//
//bertini2/io/parsing/settings_parsers/tracking.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.
//
//bertini2/io/parsing/settings_parsers/tracking.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 bertini2/io/parsing/settings_parsers/tracking.hpp. If not, see <http://www.gnu.org/licenses/>.
//
// Copyright(C) 2015 - 2017 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.
/**
\file bertini2/io/parsing/settings_parsers/tracking.hpp
\brief Provides the parsing rules for tracking-related settings in bertini2.
*/
#pragma once
#include "bertini2/io/parsing/settings_parsers/base.hpp"
#include "bertini2/trackers/config.hpp"
namespace bertini {
namespace parsing {
namespace classic {
namespace {
using namespace bertini::tracking;
}
/**
Qi Parser object for parsing config settings This ensures we can provide backwards compatibility with Bertini Classic input files.
To use this parser, construct an object of its type, then use it to parse.
\code
ConfigT conf
std::string str = "tracktype: 1; tracktolbeforeeg: 1e-8; \n";
std::string::const_iterator iter = str.begin();
std::string::const_iterator end = str.end();
bertini::ConfigSettingParser<std::string::const_iterator, ConfigT> S;
bool s = phrase_parse(iter, end, S,boost::spirit::ascii::space, conf);
\endcode
\brief Qi Parser object for parsing config file to determine settings.
*/
template<typename Iterator, typename Skipper> //boost::spirit::unused_type
struct ConfigSettingParser<Iterator, PrecisionType, Skipper> : qi::grammar<Iterator, PrecisionType(), Skipper>
{
ConfigSettingParser() : ConfigSettingParser::base_type(root_rule_, "PrecisionType")
{
namespace phx = boost::phoenix;
using qi::_1;
using qi::_2;
using qi::_3;
using qi::_4;
using qi::_val;
using qi::eps;
using qi::lit;
using qi::char_;
using qi::omit;
using boost::spirit::lexeme;
using boost::spirit::as_string;
using boost::spirit::ascii::no_case;
precisiontype_.add("0", PrecisionType::Fixed);
precisiontype_.add("1", PrecisionType::Adaptive);
precisiontype_.add("2", PrecisionType::Adaptive);
root_rule_.name("config::PrecisionType");
root_rule_ = (config_name_[_val = _1] >> -no_setting_) | no_setting_[_val = PrecisionType::Adaptive];
config_name_.name("precisiontype_");
config_name_ = *(char_ - (no_case["mptype"]>>':')) >> (no_case["mptype"] >> ':') >> precisiontype_[_val = _1] >> ';';
no_setting_.name("no_setting_");
no_setting_ = *(char_ - no_case["mptype:"]);
no_decl_.name("no_decl_");
no_decl_ = *(char_);
using phx::val;
using phx::construct;
using namespace qi::labels;
qi::on_error<qi::fail>
( root_rule_ ,
std::cout<<
val("config parser could not complete parsing. Expecting ")<<
_4<<
val(" here: ")<<
construct<std::string>(_3,_2)<<
std::endl
);
}
private:
qi::rule<Iterator, PrecisionType(), ascii::space_type > root_rule_, config_name_;
qi::rule<Iterator, ascii::space_type, std::string()> no_decl_, no_setting_;
qi::symbols<char,PrecisionType> precisiontype_;
}; //re: PrecisionTypeParser
/**
*/
template<typename Iterator, typename Skipper> //boost::spirit::unused_type
struct ConfigSettingParser<Iterator, Predictor, Skipper> : qi::grammar<Iterator, Predictor(), Skipper>
{
ConfigSettingParser() : ConfigSettingParser::base_type(root_rule_, "config::PredictorType")
{
namespace phx = boost::phoenix;
using qi::_1;
using qi::_2;
using qi::_3;
using qi::_4;
using qi::_val;
using qi::eps;
using qi::lit;
using qi::char_;
using qi::omit;
using boost::spirit::lexeme;
using boost::spirit::as_string;
using boost::spirit::ascii::no_case;
predictor_.add("-1", Predictor::Constant);
predictor_.add("0", Predictor::Euler);
predictor_.add("1", Predictor::Heun);
predictor_.add("2", Predictor::RK4);
predictor_.add("3", Predictor::Heun);
predictor_.add("4", Predictor::RKNorsett34);
predictor_.add("5", Predictor::RKF45);
predictor_.add("6", Predictor::RKCashKarp45);
predictor_.add("7", Predictor::RKDormandPrince56);
predictor_.add("8", Predictor::RKVerner67);
std::string setting_name = "odepredictor";
root_rule_.name("Predictor");
root_rule_ = (config_name_[_val = _1] >> -no_setting_) | no_setting_[_val = Predictor::RKF45];
config_name_.name("predictor_");
config_name_ = *(char_ - (no_case[setting_name] >> ':')) >> (no_case[setting_name] >> ':') >> predictor_[_val = _1] >> ';';
no_setting_.name("no_setting_");
no_setting_ = *(char_ - no_case[setting_name]);
no_decl_.name("no_decl_");
no_decl_ = *(char_);
using phx::val;
using phx::construct;
using namespace qi::labels;
qi::on_error<qi::fail>
( root_rule_ ,
std::cout<<
val("config parser could not complete parsing. Expecting ")<<
_4<<
val(" here: ")<<
construct<std::string>(_3,_2)<<
std::endl
);
}
private:
qi::rule<Iterator, Predictor(), ascii::space_type > root_rule_, config_name_;
qi::rule<Iterator, ascii::space_type, std::string()> no_decl_, no_setting_;
qi::symbols<char,Predictor> predictor_;
}; //re: PredictorTypeParser
/**
*/
template<typename Iterator, typename Skipper> //boost::spirit::unused_type
struct ConfigSettingParser<Iterator, SteppingConfig, Skipper> : qi::grammar<Iterator, SteppingConfig(), Skipper>
{
private:
using T = double;
using R = mpq_rational;
public:
ConfigSettingParser() : ConfigSettingParser::base_type(root_rule_, "config::SteppingType")
{
namespace phx = boost::phoenix;
using qi::_1;
using qi::_2;
using qi::_3;
using qi::_4;
using qi::_val;
using qi::eps;
using qi::lit;
using qi::char_;
using qi::omit;
using boost::spirit::lexeme;
using boost::spirit::as_string;
using boost::spirit::ascii::no_case;
std::string maxstep_name = "maxstepsize";
std::string stepsuccess_name = "stepsuccessfactor";
std::string stepfail_name = "stepfailfactor";
std::string stepsincrease_name = "stepsforincrease";
std::string maxnumsteps_name = "maxnumbersteps";
root_rule_.name("SteppingConfig");
root_rule_ = ((max_step_size_[phx::bind( [this](SteppingConfig & S, T num)
{
S.max_step_size = num;
}, _val, _1 )]
^ stepsize_success_[phx::bind( [this](SteppingConfig & S, R num)
{
S.step_size_success_factor = num;
}, _val, _1 )]
^ stepsize_fail_[phx::bind( [this](SteppingConfig & S, R num)
{
S.step_size_fail_factor = num;
}, _val, _1 )]
^ steps_increase_[phx::bind( [this](SteppingConfig & S, unsigned num)
{
S.consecutive_successful_steps_before_stepsize_increase = num;
}, _val, _1 )]
^ max_num_steps_[phx::bind( [this](SteppingConfig & S, unsigned num)
{
S.max_num_steps = num;
}, _val, _1 )])
>> -no_setting_)
| no_setting_;
all_names_ = (no_case[maxstep_name] >> ':') | (no_case[stepsuccess_name] >> ':')|
(no_case[stepfail_name] >> ':')| (no_case[stepsincrease_name] >> ':') | (no_case[maxnumsteps_name] >> ':');
max_step_size_.name("max_step_size_");
max_step_size_ = *(char_ - all_names_) >> (no_case[maxstep_name] >> ':')
>> mpfr_rules.rational[phx::bind( [this](T & num, std::string const& str)
{
num = bertini::NumTraits<T>::FromString(str);
}, _val, _1 )] >> ';';
stepsize_success_.name("stepsize_success_");
stepsize_success_ = *(char_ - all_names_) >> (no_case[stepsuccess_name] >> ':')
>> mpfr_rules.rational[phx::bind( [this](R & num, std::string const& str)
{
num = bertini::NumTraits<double>::FromString(str);
}, _val, _1 )] >> ';';
stepsize_fail_.name("stepsize_fail_");
stepsize_fail_ = *(char_ - all_names_) >> (no_case[stepfail_name] >> ':')
>> mpfr_rules.rational[phx::bind( [this](R & num, std::string const& str)
{
num = bertini::NumTraits<double>::FromString(str);
}, _val, _1 )] >> ';';
steps_increase_.name("steps_increase_");
steps_increase_ = *(char_ - all_names_) >> (no_case[stepsincrease_name] >> ':') >> qi::uint_[_val=_1] >> ';';
max_num_steps_.name("max_num_steps_");
max_num_steps_ = *(char_ - all_names_) >> (no_case[maxnumsteps_name] >> ':') >> qi::uint_[_val=_1] >> ';';
no_setting_.name("no_setting_");
no_setting_ = *(char_ - all_names_);
no_decl_.name("no_decl_");
no_decl_ = *(char_);
using phx::val;
using phx::construct;
using namespace qi::labels;
qi::on_error<qi::fail>
( root_rule_ ,
std::cout<<
val("config parser could not complete parsing. Expecting ")<<
_4<<
val(" here: ")<<
construct<std::string>(_3,_2)<<
std::endl
);
}
private:
qi::rule<Iterator, SteppingConfig(), ascii::space_type > root_rule_;
qi::rule<Iterator, T(), ascii::space_type > max_step_size_;
qi::rule<Iterator, R(), ascii::space_type > stepsize_success_, stepsize_fail_;
qi::rule<Iterator, unsigned int(), ascii::space_type > steps_increase_, max_num_steps_;
qi::rule<Iterator, ascii::space_type, std::string()> no_decl_, no_setting_, all_names_;
rules::LongNum<Iterator> mpfr_rules;
}; //re: SteppingParser
/**
*/
template<typename Iterator, typename Skipper> //boost::spirit::unused_type
struct ConfigSettingParser<Iterator, NewtonConfig, Skipper> : qi::grammar<Iterator, NewtonConfig(), Skipper>
{
ConfigSettingParser() : ConfigSettingParser::base_type(root_rule_, "config::NewtonType")
{
namespace phx = boost::phoenix;
using qi::_1;
using qi::_2;
using qi::_3;
using qi::_4;
using qi::_val;
using qi::eps;
using qi::lit;
using qi::char_;
using qi::omit;
using boost::spirit::lexeme;
using boost::spirit::as_string;
using boost::spirit::ascii::no_case;
std::string maxits_name = "maxnewtonits";
root_rule_.name("NewtonConfig");
root_rule_ = (max_its_[phx::bind( [this](NewtonConfig & S, unsigned num)
{
S.max_num_newton_iterations = num;
}, _val, _1 )]
>> -no_setting_)
| no_setting_;
all_names_ = eps >> (no_case[maxits_name] >> ':');
max_its_.name("max_its_");
max_its_ = *(char_ - no_case[maxits_name]) >> (no_case[maxits_name] >> ':') >> qi::uint_[_val=_1] >> ';';
no_setting_.name("no_setting_");
no_setting_ = *(char_ - all_names_);
no_decl_.name("no_decl_");
no_decl_ = *(char_);
using phx::val;
using phx::construct;
using namespace qi::labels;
qi::on_error<qi::fail>
( root_rule_ ,
std::cout<<
val("config parser could not complete parsing. Expecting ")<<
_4<<
val(" here: ")<<
construct<std::string>(_3,_2)<<
std::endl
);
}
private:
qi::rule<Iterator, NewtonConfig(), Skipper> root_rule_;
qi::rule<Iterator, unsigned int(), ascii::space_type > max_its_;
qi::rule<Iterator, ascii::space_type, std::string()> no_decl_, no_setting_, all_names_;
}; //re: NewtonParser
/**
As of this writing, there are no meaningful settings in FixedPrecisionConfig,
so this parser is ... empty
*/
template<typename Iterator, typename Skipper>
struct ConfigSettingParser<Iterator, FixedPrecisionConfig, Skipper> : qi::grammar<Iterator, FixedPrecisionConfig(), Skipper>
{
ConfigSettingParser() : ConfigSettingParser::base_type(root_rule_, "config::FixedPrecision")
{
namespace phx = boost::phoenix;
using qi::_1;
using qi::_2;
using qi::_3;
using qi::_4;
using qi::_val;
using qi::eps;
using qi::lit;
using qi::char_;
using qi::omit;
using boost::spirit::lexeme;
using boost::spirit::as_string;
using boost::spirit::ascii::no_case;
root_rule_.name("config::FixedPrecision");
root_rule_ = eps[_val = FixedPrecisionConfig()] >> omit[*(char_)];
using phx::val;
using phx::construct;
using namespace qi::labels;
qi::on_error<qi::fail>
( root_rule_ ,
std::cout<<
val("config parser could not complete parsing. Expecting ")<<
_4<<
val(" here: ")<<
construct<std::string>(_3,_2)<<
std::endl
);
}
private:
qi::rule<Iterator, FixedPrecisionConfig(), ascii::space_type > root_rule_;
}; //re: FixedPrecisionConfig Parser
using AdaptiveMultiplePrecisionConfig = AdaptiveMultiplePrecisionConfig;
template<typename Iterator, typename Skipper>
struct ConfigSettingParser<Iterator, AdaptiveMultiplePrecisionConfig, Skipper> : qi::grammar<Iterator, AdaptiveMultiplePrecisionConfig(), Skipper>
{
ConfigSettingParser() : ConfigSettingParser::base_type(root_rule_, "AdaptiveMultiplePrecisionConfig")
{
using T = double;
namespace phx = boost::phoenix;
using qi::_1;
using qi::_2;
using qi::_3;
using qi::_4;
using qi::_val;
using qi::eps;
using qi::lit;
using qi::char_;
using qi::omit;
using boost::spirit::lexeme;
using boost::spirit::as_string;
using boost::spirit::ascii::no_case;
std::string coefficient_bound_name = "coefficientbound";
std::string degree_bound_name = "degreebound";
std::string lin_solve_error_bnd_name = "epsilon";
std::string jac_eval_err_bnd_name = "phi";
std::string func_eval_err_bnd_name = "psi";
std::string safety_one_name = "ampsafetydigits1";
std::string safety_two_name = "ampsafetydigits2";
std::string max_prec_name = "ampmaxprec";
std::string consec_steps_prec_dec_name = "maxstepsprecisiondecrease";
std::string max_num_prec_decs_name = "maxnumprecdecreases";
root_rule_.name("config::AMP");
root_rule_ = ((coefficient_bound_[phx::bind( [this](AdaptiveMultiplePrecisionConfig & S, T num)
{
S.coefficient_bound = num;
}, _val, _1 )]
^ degree_bound_[phx::bind( [this](AdaptiveMultiplePrecisionConfig & S, T num)
{
S.degree_bound = num;
}, _val, _1 )]
^ lin_solve_error_bnd_[phx::bind( [this](AdaptiveMultiplePrecisionConfig & S, T num)
{
S.epsilon = num;
}, _val, _1 )]
^ jac_eval_err_bnd_[phx::bind( [this](AdaptiveMultiplePrecisionConfig & S, T num)
{
S.Phi = num;
}, _val, _1 )]
^ func_eval_err_bnd_[phx::bind( [this](AdaptiveMultiplePrecisionConfig & S, T num)
{
S.Psi = num;
}, _val, _1 )]
^ safety_one_[phx::bind( [this](AdaptiveMultiplePrecisionConfig & S, int num)
{
S.safety_digits_1 = num;
}, _val, _1 )]
^ safety_two_[phx::bind( [this](AdaptiveMultiplePrecisionConfig & S, int num)
{
S.safety_digits_2 = num;
}, _val, _1 )]
^ max_prec_[phx::bind( [this](AdaptiveMultiplePrecisionConfig & S, unsigned num)
{
S.maximum_precision = num;
}, _val, _1 )]
^ consec_steps_prec_dec_[phx::bind( [this](AdaptiveMultiplePrecisionConfig & S, unsigned num)
{
S.consecutive_successful_steps_before_precision_decrease = num;
}, _val, _1 )]
^ max_num_prec_decs_[phx::bind( [this](AdaptiveMultiplePrecisionConfig & S, unsigned num)
{
S.max_num_precision_decreases = num;
}, _val, _1 )]
)
>> -no_setting_) | no_setting_;
all_names_ = (no_case[coefficient_bound_name] >> ':') |
(no_case[degree_bound_name] >> ':') |
(no_case[lin_solve_error_bnd_name] >> ':') |
(no_case[jac_eval_err_bnd_name] >> ':') |
(no_case[func_eval_err_bnd_name] >> ':') |
(no_case[safety_one_name] >> ':') |
(no_case[safety_two_name] >> ':') |
(no_case[max_prec_name] >> ':') |
(no_case[consec_steps_prec_dec_name] >> ':') |
(no_case[max_num_prec_decs_name] >> ':')
;
auto str_to_T = [this](T & num, std::string const& str)
{
// std::cout << str << std::endl;
num = bertini::NumTraits<T>::FromString(str);
};
degree_bound_.name("degree_bound_");
degree_bound_ = *(char_ - all_names_) >> (no_case[degree_bound_name] >> ':')
>> mpfr_rules.number_string_[phx::bind( str_to_T, _val, _1 )] >> ';';
coefficient_bound_.name("coefficient_bound_");
coefficient_bound_ = *(char_ - all_names_) >> (no_case[coefficient_bound_name] >> ':')
>> mpfr_rules.number_string_[phx::bind( str_to_T, _val, _1 )] >> ';';
lin_solve_error_bnd_.name("lin_solve_error_bnd_");
lin_solve_error_bnd_ = *(char_ - all_names_) >> (no_case[lin_solve_error_bnd_name] >> ':')
>> mpfr_rules.number_string_[phx::bind( str_to_T, _val, _1 )] >> ';';
jac_eval_err_bnd_.name("jac_eval_err_bnd_");
jac_eval_err_bnd_ = *(char_ - all_names_) >> (no_case[jac_eval_err_bnd_name] >> ':')
>> mpfr_rules.number_string_[phx::bind( str_to_T, _val, _1 )] >> ';';
func_eval_err_bnd_.name("func_eval_err_bnd_");
func_eval_err_bnd_ = *(char_ - all_names_) >> (no_case[func_eval_err_bnd_name] >> ':')
>> mpfr_rules.number_string_[phx::bind( str_to_T, _val, _1 )] >> ';';
safety_one_.name("safety_one_");
safety_one_ = *(char_ - all_names_) >> (no_case[safety_one_name] >> ':') >> qi::int_[_val=_1] >> ';';
safety_two_.name("safety_two_");
safety_two_ = *(char_ - all_names_) >> (no_case[safety_two_name] >> ':') >> qi::int_[_val=_1] >> ';';
max_prec_.name("max_prec_");
max_prec_ = *(char_ - all_names_) >> (no_case[max_prec_name] >> ':') >> qi::uint_[_val=_1] >> ';';
consec_steps_prec_dec_.name("consec_steps_prec_dec_");
consec_steps_prec_dec_ = *(char_ - all_names_) >> (no_case[consec_steps_prec_dec_name] >> ':') >> qi::uint_[_val=_1] >> ';';
max_num_prec_decs_.name("max_num_prec_decs_");
max_num_prec_decs_ = *(char_ - all_names_) >> (no_case[max_num_prec_decs_name] >> ':') >> qi::uint_[_val=_1] >> ';';
no_setting_.name("no_setting_");
no_setting_ = *(char_ - all_names_);
no_decl_.name("no_decl_");
no_decl_ = *(char_);
using phx::val;
using phx::construct;
using namespace qi::labels;
qi::on_error<qi::fail>
( root_rule_ ,
std::cout<<
val("config parser could not complete parsing. Expecting ")<<
_4<<
val(" here: ")<<
construct<std::string>(_3,_2)<<
std::endl
);
}
private:
qi::rule<Iterator, AdaptiveMultiplePrecisionConfig(), ascii::space_type > root_rule_;
qi::rule<Iterator, double(), ascii::space_type > degree_bound_, coefficient_bound_, lin_solve_error_bnd_, jac_eval_err_bnd_, func_eval_err_bnd_;
qi::rule<Iterator, int(), ascii::space_type > safety_one_, safety_two_;
qi::rule<Iterator, unsigned int(), ascii::space_type > max_prec_, consec_steps_prec_dec_, max_num_prec_decs_;
qi::rule<Iterator, ascii::space_type, std::string()> no_decl_, no_setting_, all_names_;
rules::LongNum<Iterator> mpfr_rules;
}; //re: AMPParser
} // re: namespace classic
}// re: namespace parsing
}// re: namespace bertini

View File

@@ -0,0 +1,32 @@
//This file is part of Bertini 2.
//
//bertini2/io/parsers.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.
//
//bertini2/io/parsing/settings_parsers.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 bertini2/io/parsing/settings_parsers.hpp. If not, see <http://www.gnu.org/licenses/>.
//
// Copyright(C) 2015 - 2017 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.
/**
\file bertini2/io/parsing/settings_parsers.hpp
\brief Useful Qi rules for parsing settings
*/
#pragma once

View File

@@ -0,0 +1,96 @@
//This file is part of Bertini 2.
//
//bertini2/io/parsers.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.
//
//bertini2/io/parsing/system_parsers.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 bertini2/io/parsing/system_parsers.hpp. If not, see <http://www.gnu.org/licenses/>.
//
// Copyright(C) 2015 - 2017 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.
/**
\file bertini2/io/parsing/system_parsers.hpp
\brief Provides the parsers for systems in bertini2.
*/
#pragma once
#include "bertini2/io/parsing/system_rules.hpp"
namespace bertini {
namespace parsing {
namespace classic {
template <typename Iterator>
static bool parse(Iterator first, Iterator last, System& sys)
{
using boost::spirit::qi::double_;
using boost::spirit::qi::_1;
using boost::spirit::qi::phrase_parse;
using boost::spirit::ascii::space;
using boost::phoenix::ref;
SystemParser<Iterator> S;
System s{};
bool r = phrase_parse(first, last,
S,
space,
s);
if (!r || first != last) // fail if we did not get a full match
return false;
sys = s;
return r;
}
} // re: namespace classic
}// re: namespace parsing
inline
System::System(std::string const& input)
{
System sys;
parsing::classic::SystemParser<std::string::const_iterator> S;
std::string::const_iterator iter = input.begin();
std::string::const_iterator end = input.end();
bool s = phrase_parse(iter, end, S,boost::spirit::ascii::space, sys);
if (!s || iter!=end)
{
throw std::runtime_error("unable to correctly parse string in construction of system");
}
using std::swap;
swap(sys,*this);
}
}// re: namespace bertini

View File

@@ -0,0 +1,379 @@
//This file is part of Bertini 2.
//
//bertini2/io/parsers.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.
//
//bertini2/io/parsing/system_rules.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 bertini2/io/parsing/system_rules.hpp. If not, see <http://www.gnu.org/licenses/>.
//
// Copyright(C) 2015 - 2017 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.
/**
\file bertini2/io/parsing/system_rules.hpp
\brief Provides the parsing rules for systems in bertini2.
*/
#pragma once
#include "bertini2/io/parsing/qi_files.hpp"
#include "bertini2/system/system.hpp"
#include "bertini2/io/parsing/function_rules.hpp"
namespace bertini {
namespace parsing {
namespace classic {
// a few local using statements to reduce typing etc.
using Function = node::Function;
using Variable = node::Variable;
using Node = node::Node;
using Fn = std::shared_ptr<Function>;
using Var = std::shared_ptr<Variable>;
using Nd = std::shared_ptr<Node>;
/**
Qi Parser object for parsing text into the System class. This ensures we can provide backwards compatibility with Bertini Classic input files.
To use this parser, construct an object of its type, then use it to parse.
\code
System sys;
std::string str = "variable_group x, y, z; \nfunction f1, f2;\n f1 = x*y*z;\n f2 = x+y+z;\n";
std::string::const_iterator iter = str.begin();
std::string::const_iterator end = str.end();
bertini::SystemParser<std::string::const_iterator> S;
bool s = phrase_parse(iter, end, S,boost::spirit::ascii::space, sys);
\endcode
\brief Qi Parser object for parsing text into the System class.
This parser could not have been written without the help of SO user sehe.
*/
template<typename Iterator, typename Skipper = ascii::space_type>
struct SystemParser : qi::grammar<Iterator, System(), Skipper>
{
SystemParser() : function_parser_(&encountered_symbols_),
/*initialize here with address of encountered_symbols*/
SystemParser::base_type(root_rule_)
{
namespace phx = boost::phoenix;
using qi::_1;
using qi::_2;
using qi::_3;
using qi::_4;
using qi::_val;
using qi::eps;
using qi::lit;
using boost::spirit::lexeme;
declarative_symbols_.add("variable_group",0);
declarative_symbols_.add("hom_variable_group",1);
declarative_symbols_.add("variable",2);
declarative_symbols_.add("function",3);
declarative_symbols_.add("constant",4);
declarative_symbols_.add("parameter",5);
declarative_symbols_.add("implicit_parameter",6);
declarative_symbols_.add("pathvariable",7);
declarative_symbols_.add("random",8);
declarative_symbols_.add("random_real",9);
special_numbers_.add("pi", node::Pi());
special_numbers_.add("Pi", special_numbers_.at("pi"));
special_numbers_.add("e", node::E());
special_numbers_.add("E", special_numbers_.at("e"));
special_numbers_.add("i", node::I());
special_numbers_.add("I", special_numbers_.at("i"));
encountered_symbols_.add("pi", special_numbers_.at("pi"));
encountered_symbols_.add("Pi", special_numbers_.at("pi"));
encountered_symbols_.add("e", special_numbers_.at("e"));
encountered_symbols_.add("E", special_numbers_.at("e"));
encountered_symbols_.add("i", special_numbers_.at("i"));
encountered_symbols_.add("I", special_numbers_.at("i"));
//TODO refine this so that counts are enforced at parse time?
root_rule_.name("system_parsing");
root_rule_ =
*(
variable_group_ [phx::bind(&System::AddVariableGroup, _val, _1)]
|
hom_variable_group_ [phx::bind(&System::AddHomVariableGroup, _val, _1)]
|
variables_ [phx::bind(&System::AddUngroupedVariables, _val, _1)]
|
functions_ [phx::bind(&System::AddFunctions, _val, _1)]
|
constants_ [phx::bind(&System::AddConstants, _val, _1)]
|
parameters_ [phx::bind(&System::AddParameters, _val, _1)]
|
implicit_parameters_ [phx::bind(&System::AddImplicitParameters, _val, _1)]
|
path_variable_ [phx::bind(&System::AddPathVariable, _val, _1)]
|
subfunction_ [phx::bind(&System::AddSubfunction, _val, _1)]
|
definition_
)
;
variables_.name("variables_"); hom_variable_group_.name("hom_variable_group_"); variable_group_.name("variable_group_"); implicit_parameters_.name("implicit_parameters_");
variables_ = "variable" > genericvargp_ > ';';
hom_variable_group_ = "hom_variable_group" > genericvargp_ > ';';
variable_group_ = "variable_group" > genericvargp_ > ';';
implicit_parameters_ = "implicit_parameter" > genericvargp_ > ';';
path_variable_.name("path_variable_");
path_variable_ = "pathvariable" > new_variable_ > ';';
genericvargp_.name("genericvargp_");
genericvargp_ = new_variable_ % ',';
new_variable_.name("new_variable_");
new_variable_ = unencountered_symbol_ [boost::phoenix::bind( [this](Var & V, std::string str)
{
MakeAndAddVariable(V,str);
}, _val, _1 )];
functions_.name("functions_"); constants_.name("constants_"); parameters_.name("parameters_");
functions_ = "function" > genericfuncgp_ > ';';
constants_ = "constant" > genericfuncgp_ > ';';
parameters_ = "parameter" > genericfuncgp_ > ';';
genericfuncgp_.name("genericfuncgp_");
genericfuncgp_ = new_function_ % ',';
new_function_.name("new_function_");
new_function_ = unencountered_symbol_ [boost::phoenix::bind( [this](Fn & F, std::string str)
{
MakeAndAddFunction(F,str);
}, _val, _1 )];//[_val = make_shared_<Function>() (_1)]
// this rule gets a string.
unencountered_symbol_.name("unencountered_symbol_");
unencountered_symbol_ = valid_variable_name_ - lexeme[( declarative_symbols_ | encountered_symbols_ )];
// i am unsure about the use of lexeme in the above rule (unencountered_symbol).
// get a string which fits the naming rules.
valid_variable_name_.name("valid_variable_name_");
valid_variable_name_ = +qi::alpha >> *(qi::alnum | qi::char_("[]_") );
definition_.name("definition_");
definition_ = (encountered_functions_ > '=' > function_parser_ > ';') [phx::bind( [](const Fn & F, const Nd & N)
{
F->SetRoot(N);
},_1, _2)] ;
using qi::_a;
using qi::omit;
subfunction_.name("subfunction");
subfunction_ = new_function_ [_a = _1] > '=' >
function_parser_ [_val = _a, phx::bind( [](Fn & F, const Nd & N)
{
F->SetRoot(N);
},_a, _1)]
// omit close
> ';';
// debug(root_rule_);
//
//
//
// debug(functions_);
// debug(constants_);
// debug(parameters_);
//
// debug(genericfuncgp_);
// debug(new_function_);
//
//
//
// debug(definition_);
//
// debug(subfunction_);
//
//
//
//
// debug(variables_);
// debug(hom_variable_group_);
// debug(variable_group_);
// debug(implicit_parameters_);
// debug(path_variable_);
//
// debug(new_variable_);
// debug(genericvargp_); debug(variable_group_);
//
// debug(unencountered_symbol_);
//
// debug(valid_variable_name_);
// BOOST_SPIRIT_DEBUG_NODES( (unencountered_symbol_) (new_variable_) (genericvargp_))
using phx::val;
using phx::construct;
using namespace qi::labels;
qi::on_error<qi::fail>
( root_rule_ ,
std::cout<<
val("System parser could not complete parsing. Expecting ")<<
_4<<
val(" here: ")<<
construct<std::string>(_3,_2)<<
std::endl
);
}
private:
// rule declarations. these are member variables for the parser.
qi::rule<Iterator, System(), Skipper > root_rule_;
qi::rule<Iterator, VariableGroup(), Skipper > variable_group_, hom_variable_group_, variables_, implicit_parameters_;
qi::rule<Iterator, VariableGroup(), Skipper > genericvargp_;
qi::rule<Iterator, Var(), Skipper> path_variable_;
qi::rule<Iterator, Var()> new_variable_;
qi::rule<Iterator, std::vector<Fn>(), Skipper > functions_, constants_, parameters_;
qi::rule<Iterator, std::vector<Fn>(), Skipper > genericfuncgp_;
qi::rule<Iterator, Fn(), Skipper, qi::locals<Fn> > subfunction_;
qi::rule<Iterator, Fn()> new_function_;
qi::rule<Iterator, std::string()> unencountered_symbol_;
// the rule which determines valid variable names
qi::rule<Iterator, std::string()> valid_variable_name_;
qi::rule<Iterator, Skipper, qi::unused_type> definition_;
// symbol declarations
qi::symbols<char,Nd> encountered_symbols_;
qi::symbols<char,int> declarative_symbols_;
qi::symbols<char,Fn> encountered_functions_;
qi::symbols<char,Nd> special_numbers_;
FunctionParser<Iterator> function_parser_;
/**
To accompany the rule for making new functions when you encounter a new symbol.
Simultaneously makes a new function, and adds it to the set of symbols.
*/
void MakeAndAddFunction(Fn & F, std::string str)
{
F = Function::Make(str);
encountered_symbols_.add(str, F);
encountered_functions_.add(str,F);
}
/**
To accompany the rule for making new variables when you encounter a new symbol.
Simultaneously makes a new variable, and adds it to the set of symbols.
*/
void MakeAndAddVariable(Var & V, std::string str)
{
V = Variable::Make(str);
encountered_symbols_.add(str, V);
}
void SetRootNode(Fn & F, const Nd & N)
{
F->SetRoot(N);
}
};
} // re: namespace classic
} //re: namespace parsing
} // re: namespace bertini