move paradiseo/eo to deprecated/ before merge with eodev
This commit is contained in:
parent
948da627ea
commit
0c5120f675
717 changed files with 0 additions and 0 deletions
891
deprecated/eo/contrib/mathsym/fun/FunDef.cpp
Normal file
891
deprecated/eo/contrib/mathsym/fun/FunDef.cpp
Normal file
|
|
@ -0,0 +1,891 @@
|
|||
/*
|
||||
* Copyright (C) 2005 Maarten Keijzer
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of version 2 of the GNU General Public License as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This program 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 this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
|
||||
#include <sstream>
|
||||
#include "Sym.h"
|
||||
#include "FunDef.h"
|
||||
#include <LanguageTable.h>
|
||||
|
||||
using namespace std;
|
||||
using namespace boost::numeric;
|
||||
|
||||
vector<const FunDef*> language;
|
||||
|
||||
token_t add_function(FunDef* function) {
|
||||
language.push_back(function);
|
||||
return token_t(language.size()-1);
|
||||
}
|
||||
|
||||
const FunDef& get_element(token_t token) { return *language[token]; }
|
||||
|
||||
/* Printing */
|
||||
|
||||
string c_print(const Sym& sym) {
|
||||
return c_print(sym, vector<string>());
|
||||
}
|
||||
|
||||
string c_print(const Sym& sym, const vector<string>& vars) {
|
||||
const SymVec& args = sym.args();
|
||||
vector<string> names(args.size());
|
||||
for (unsigned i = 0; i < args.size(); ++i) {
|
||||
names[i] = c_print(args[i], vars);
|
||||
}
|
||||
return language[sym.token()]->c_print(names, vars);
|
||||
}
|
||||
|
||||
/* Evaluation */
|
||||
|
||||
|
||||
double eval(const Sym& sym, const std::vector<double>& inputs) {
|
||||
return language[sym.token()]->eval(sym.args(), inputs);
|
||||
}
|
||||
|
||||
|
||||
/* Interval Logic */
|
||||
Interval eval(const Sym& sym, const vector<Interval>& inputs) {
|
||||
const SymVec& args = sym.args();
|
||||
vector<Interval> interv(args.size());
|
||||
for (unsigned i = 0; i < args.size(); ++i) {
|
||||
interv[i] = eval(args[i], inputs);
|
||||
|
||||
if (!valid(interv[i])) throw interval_error();
|
||||
}
|
||||
return language[sym.token()]->eval(interv, inputs);
|
||||
}
|
||||
|
||||
/* */
|
||||
void add_function_to_table(LanguageTable& table, token_t token) {
|
||||
const FunDef& fundef = *language[token];
|
||||
|
||||
if (fundef.has_varargs() == false) {
|
||||
table.add_function(token, fundef.min_arity());
|
||||
} else { // sum or prod (or min or max)
|
||||
table.add_function(token, 2);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// by default it is eager
|
||||
double FunDef::eval(const SymVec& args, const vector<double>& inputs) const {
|
||||
vector<double> values(args.size());
|
||||
for (unsigned i = 0; i < args.size(); ++i) {
|
||||
values[i] = ::eval(args[i], inputs);
|
||||
}
|
||||
|
||||
return eval(values, inputs);
|
||||
}
|
||||
|
||||
/* Variable Handling */
|
||||
FunDef* make_var(int idx); // defined in FunDefs.h
|
||||
static vector<token_t> var_token;
|
||||
|
||||
Sym SymVar(unsigned idx) {
|
||||
if (var_token.size() <= idx) {
|
||||
// it is new
|
||||
var_token.resize(idx+1, token_t(-1));
|
||||
var_token[idx] = add_function( make_var(idx) );
|
||||
} else if (var_token[idx] == token_t(-1)) {
|
||||
var_token[idx] = add_function( make_var(idx) );
|
||||
}
|
||||
return Sym(var_token[idx]);
|
||||
}
|
||||
|
||||
|
||||
/* Constant Handling */
|
||||
|
||||
struct HashDouble{
|
||||
size_t operator()(double val) const {
|
||||
unsigned long h = 0;
|
||||
char* s = (char*)&val;
|
||||
for (unsigned i=0 ; i<sizeof(double); ++i)
|
||||
h = 5*h + s[i];
|
||||
return size_t(h);
|
||||
}
|
||||
};
|
||||
|
||||
#if USE_TR1
|
||||
typedef std::tr1::unordered_map<double, token_t> DoubleSet;
|
||||
typedef std::tr1::unordered_map<Sym, token_t> LambdaSet;
|
||||
#else
|
||||
typedef hash_map<double, token_t, HashDouble> DoubleSet;
|
||||
typedef hash_map<Sym, token_t, HashSym> LambdaSet;
|
||||
#endif
|
||||
|
||||
static DoubleSet doubleSet; // for quick checking if a constant already exists
|
||||
static vector<double> token_value;
|
||||
|
||||
static LambdaSet lambdaSet;
|
||||
static vector<Sym> token_lambda;
|
||||
|
||||
static std::vector<token_t> free_list;
|
||||
|
||||
void delete_val(token_t token) { // clean up the information about this value
|
||||
|
||||
if (is_constant(token)) {
|
||||
//cout << "Deleting constant token " << token << endl;
|
||||
double value = token_value[token];
|
||||
doubleSet.erase(value);
|
||||
|
||||
delete language[token];
|
||||
language[token] = 0;
|
||||
free_list.push_back(token);
|
||||
}
|
||||
else if (is_lambda(token)) {
|
||||
//cout << "Deleting lambda token " << token << endl;
|
||||
|
||||
Sym expression = token_lambda[token];
|
||||
lambdaSet.erase(expression);
|
||||
|
||||
delete language[token];
|
||||
language[token] = 0;
|
||||
free_list.push_back(token);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
FunDef* make_const(double value);
|
||||
|
||||
void extend_free_list();
|
||||
|
||||
Sym SymConst(double value) {
|
||||
|
||||
DoubleSet::iterator it = doubleSet.find(value);
|
||||
|
||||
if (it != doubleSet.end()) {
|
||||
return Sym(it->second); // already exists
|
||||
}
|
||||
|
||||
|
||||
if (free_list.empty()) { // make space for tokens;
|
||||
extend_free_list();
|
||||
}
|
||||
|
||||
token_t token = free_list.back();
|
||||
free_list.pop_back();
|
||||
//cout << "Creating constant with token " << token << endl;
|
||||
assert(language[token] == 0);
|
||||
|
||||
language[token] = make_const(value);
|
||||
|
||||
doubleSet[value] = token;
|
||||
if (token_value.size() < token) token_value.resize(token+1);
|
||||
token_value[token] = value;
|
||||
|
||||
return Sym(token);
|
||||
}
|
||||
|
||||
/* LanguageTable depends on this one, XXX move somewhere safe.*/
|
||||
#include <utils/eoRNG.h>
|
||||
extern Sym default_const() { return SymConst(rng.normal()); }
|
||||
|
||||
/* The functions */
|
||||
namespace {
|
||||
|
||||
class Var : public FunDef {
|
||||
public :
|
||||
unsigned idx;
|
||||
string default_str;
|
||||
|
||||
Var(unsigned _idx) : idx(_idx) {
|
||||
ostringstream os;
|
||||
os << "x[" << idx << ']'; // CompiledCode expects this form
|
||||
default_str = os.str();
|
||||
}
|
||||
|
||||
double eval(const vector<double>& _, const vector<double>& inputs) const { return inputs[idx]; }
|
||||
double eval(const SymVec& _, const vector<double>& inputs) const { return inputs[idx]; }
|
||||
string c_print(const vector<string>& _, const vector<string>& names) const {
|
||||
if (names.empty()) {
|
||||
return default_str;
|
||||
}
|
||||
return names[idx];
|
||||
}
|
||||
|
||||
Interval eval(const vector<Interval>& _, const vector<Interval>& inputs) const {
|
||||
return inputs[idx];
|
||||
}
|
||||
|
||||
unsigned min_arity() const { return 0; }
|
||||
|
||||
string name() const { return "var"; }
|
||||
|
||||
};
|
||||
|
||||
class Const : public FunDef {
|
||||
public:
|
||||
double value;
|
||||
string value_str;
|
||||
|
||||
Const(double _value) : value(_value) {
|
||||
ostringstream os;
|
||||
os.precision(17);
|
||||
os.setf(ios::showpoint);
|
||||
os << '(' << value << ')';
|
||||
value_str = os.str();
|
||||
}
|
||||
|
||||
|
||||
double eval(const vector<double>& _, const vector<double>& inputs) const { return value; }
|
||||
double eval(const SymVec& _, const vector<double>& inputs) const { return value; }
|
||||
string c_print(const vector<string>& _, const vector<string>& names) const {
|
||||
return value_str;
|
||||
}
|
||||
|
||||
Interval eval(const vector<Interval>& _, const vector<Interval>& inputs) const {
|
||||
return Interval(value);
|
||||
}
|
||||
|
||||
unsigned min_arity() const { return 0; }
|
||||
|
||||
string name() const { return "parameter"; }
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
void get_constants(Sym sym, vector<double>& ret) {
|
||||
token_t token = sym.token();
|
||||
if (is_constant(token)) {
|
||||
double val = static_cast<const Const*>(language[token])->value;
|
||||
ret.push_back(val);
|
||||
}
|
||||
|
||||
const SymVec& args = sym.args();
|
||||
for (unsigned i = 0; i < args.size(); ++i) {
|
||||
get_constants(args[i], ret);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
double get_constant_value(token_t token) {
|
||||
return static_cast<const Const*>(language[token])->value;
|
||||
}
|
||||
|
||||
/** Get out the values for all constants in the expression */
|
||||
vector<double> get_constants(Sym sym) {
|
||||
vector<double> retval;
|
||||
get_constants(sym, retval);
|
||||
return retval;
|
||||
}
|
||||
|
||||
/** Set the values for all constants in the expression. Vector needs to be the same size as the one get_constants returns
|
||||
* The argument isn't touched, it will return a new sym with the constants set. */
|
||||
Sym set_constants(Sym sym, vector<double>::const_iterator& it) {
|
||||
|
||||
token_t token = sym.token();
|
||||
if (is_constant(token)) {
|
||||
return SymConst(*it++);
|
||||
}
|
||||
|
||||
SymVec args = sym.args();
|
||||
for (unsigned i = 0; i < args.size(); ++i) {
|
||||
args[i] = set_constants(args[i], it);
|
||||
}
|
||||
|
||||
return Sym(token, args);
|
||||
}
|
||||
|
||||
Sym set_constants(Sym sym, const vector<double>& constants) {
|
||||
vector<double>::const_iterator it = constants.begin();
|
||||
return set_constants(sym, it);
|
||||
}
|
||||
|
||||
// Get functions out, excluding Const and Var
|
||||
vector<const FunDef*> get_defined_functions() {
|
||||
vector<const FunDef*> res;
|
||||
for (unsigned i = 0; i < language.size(); ++i) {
|
||||
res.push_back(language[i]);
|
||||
|
||||
if (is_constant(i) || is_variable(i)) {
|
||||
res.back() = 0; // erase
|
||||
}
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
FunDef* make_var(int idx) { return new Var(idx); }
|
||||
FunDef* make_const(double value) { return new Const(value); }
|
||||
|
||||
bool is_constant(token_t token) {
|
||||
const Const* cnst = dynamic_cast<const Const*>( language[token] );
|
||||
return cnst != 0;
|
||||
}
|
||||
|
||||
bool is_variable(token_t token) {
|
||||
const Var* var = dynamic_cast<const Var*>( language[token] );
|
||||
return var != 0;
|
||||
}
|
||||
|
||||
unsigned get_variable_index(token_t token) {
|
||||
const Var* var = static_cast<const Var*>( language[token] );
|
||||
return var->idx;
|
||||
}
|
||||
|
||||
namespace {
|
||||
class Lambda : public FunDef {
|
||||
public:
|
||||
Sym expression;
|
||||
int arity;
|
||||
|
||||
Lambda(Sym expr, int arity_) : expression(expr), arity(arity_) {}
|
||||
|
||||
double eval(const vector<double>& vals, const vector<double>& _) const {
|
||||
return ::eval(expression, vals);
|
||||
}
|
||||
|
||||
string c_print(const vector<string>& args, const vector<string>& _) const {
|
||||
return string("/*f*/") + ::c_print(expression, args) + string("/*eof*/");
|
||||
}
|
||||
|
||||
Interval eval(const vector<Interval>& args, const vector<Interval>& _) const {
|
||||
return ::eval(expression, args);
|
||||
}
|
||||
|
||||
unsigned min_arity() const { return arity; }
|
||||
string name() const { return "F"; }
|
||||
|
||||
};
|
||||
Sym normalize(Sym sym, SymVec& args) {
|
||||
// check if it's a variable
|
||||
token_t token = sym.token();
|
||||
const Var* var = dynamic_cast< const Var*>(language[token]);
|
||||
|
||||
if (var != 0) {
|
||||
for (unsigned i = 0; i < args.size(); ++i) {
|
||||
if (sym == args[i]) {
|
||||
return SymVar(i); // replace with reference to arg
|
||||
}
|
||||
}
|
||||
|
||||
// not replaced, add it
|
||||
args.push_back(sym);
|
||||
return SymVar(args.size()-1);
|
||||
|
||||
}
|
||||
|
||||
SymVec a = sym.args();
|
||||
for (unsigned i = 0; i < a.size(); ++i) {
|
||||
a[i] = normalize(a[i], args);
|
||||
}
|
||||
|
||||
return Sym(token, a);
|
||||
}
|
||||
}
|
||||
|
||||
bool is_lambda(token_t token) {
|
||||
const Lambda* lambda = dynamic_cast<const Lambda*>( language[token]);
|
||||
return lambda != 0;
|
||||
}
|
||||
|
||||
std::ostream& print_list(Sym sym, ostream& os) {
|
||||
os << sym.token() << ' ';
|
||||
|
||||
const SymVec& args = sym.args();
|
||||
for (unsigned i = 0; i < args.size(); ++i) {
|
||||
print_list(args[i], os);
|
||||
}
|
||||
return os;
|
||||
}
|
||||
|
||||
token_t new_lambda(Sym sym, int arity) {
|
||||
// check if already present
|
||||
|
||||
LambdaSet::iterator it = lambdaSet.find(sym);
|
||||
if (it != lambdaSet.end()) {
|
||||
return it->second;
|
||||
}
|
||||
|
||||
|
||||
// new, insert
|
||||
Lambda* lambda = new Lambda(sym, arity);
|
||||
|
||||
if (free_list.empty()) {
|
||||
extend_free_list();
|
||||
}
|
||||
|
||||
token_t token = free_list.back();
|
||||
free_list.pop_back();
|
||||
language[token] = lambda;
|
||||
|
||||
lambdaSet[sym] = token;
|
||||
if (token_lambda.size() <= token) token_lambda.resize(token+1);
|
||||
token_lambda[token] = sym;
|
||||
|
||||
return token;
|
||||
}
|
||||
|
||||
/* Compression */
|
||||
typedef hash_map<Sym, unsigned, HashSym> OccMap;
|
||||
|
||||
void count_occurances(Sym sym, OccMap& occ) {
|
||||
occ[sym]++;
|
||||
const SymVec& args = sym.args();
|
||||
for (unsigned i = 0; i < args.size(); ++i) {
|
||||
count_occurances(args[i], occ);
|
||||
}
|
||||
}
|
||||
|
||||
Sym create_lambda(Sym sym, OccMap& occ, unsigned nvars, vector<Sym>& args) {
|
||||
unsigned o = occ[sym];
|
||||
unsigned sz = sym.size();
|
||||
|
||||
if (o * sz > o + sz + nvars || is_variable(sym.token()) ) {
|
||||
// check if it's already present
|
||||
for (unsigned i = 0; i < args.size(); ++i) {
|
||||
if (args[i] == sym) {
|
||||
return SymVar(i);
|
||||
}
|
||||
}
|
||||
// push_back
|
||||
args.push_back(sym);
|
||||
return SymVar(args.size()-1);
|
||||
}
|
||||
|
||||
SymVec sym_args = sym.args();
|
||||
for (unsigned i = 0; i < sym_args.size(); ++i) {
|
||||
sym_args[i] = create_lambda(sym_args[i], occ, nvars, args);
|
||||
}
|
||||
|
||||
return Sym(sym.token(), sym_args);
|
||||
|
||||
}
|
||||
|
||||
Sym compress(Sym sym) {
|
||||
OccMap occ(sym.size());
|
||||
count_occurances(sym, occ);
|
||||
|
||||
unsigned nvars = 0;
|
||||
for (OccMap::iterator it = occ.begin(); it != occ.end(); ++it) {
|
||||
if (is_variable(it->first.token())) nvars++;
|
||||
}
|
||||
|
||||
SymVec args;
|
||||
Sym body = create_lambda(sym, occ, nvars, args);
|
||||
|
||||
|
||||
if (body.size() < sym.size()) {
|
||||
// see if the body can be compressed some more
|
||||
body = compress(body);
|
||||
|
||||
token_t token = new_lambda(body, args.size());
|
||||
|
||||
for (unsigned i = 0; i < args.size(); ++i) {
|
||||
args[i] = compress(args[i]);
|
||||
}
|
||||
|
||||
Sym result = Sym(token, args);
|
||||
return compress(result); // see if it can be compressed some more
|
||||
}
|
||||
|
||||
return sym;
|
||||
}
|
||||
|
||||
Sym SymLambda(Sym expr) { return compress(expr); }
|
||||
|
||||
Sym expand(Sym expr, const SymVec& args) {
|
||||
|
||||
const Var* var = dynamic_cast<const Var*>( language[expr.token()] );
|
||||
if (var != 0) {
|
||||
return args[var->idx];
|
||||
}
|
||||
|
||||
SymVec expr_args = expr.args();
|
||||
for (unsigned i = 0; i < expr_args.size(); ++i) {
|
||||
expr_args[i] = expand(expr_args[i], args);
|
||||
}
|
||||
|
||||
return Sym(expr.token(), expr_args);
|
||||
}
|
||||
|
||||
Sym SymUnlambda(Sym sym) {
|
||||
Sym retval = sym;
|
||||
const Lambda* lambda = dynamic_cast<const Lambda*>( language[sym.token()] );
|
||||
if (lambda != 0) {
|
||||
retval = expand(lambda->expression, sym.args());
|
||||
}
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
Sym expand_all(Sym sym) {
|
||||
SymVec args = sym.args();
|
||||
for (unsigned i = 0; i < args.size(); ++i) {
|
||||
args[i] = expand_all(args[i]);
|
||||
}
|
||||
|
||||
Sym nw = SymUnlambda( Sym(sym.token(), args) );
|
||||
|
||||
if (nw != sym) {
|
||||
nw = expand_all(nw);
|
||||
}
|
||||
|
||||
return nw;
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
class Sum : public FunDef {
|
||||
|
||||
public :
|
||||
|
||||
double eval(const vector<double>& vals, const vector<double>& _) const {
|
||||
double res = 0;
|
||||
for (unsigned i = 0; i < vals.size(); ++i) res += vals[i];
|
||||
return res;
|
||||
}
|
||||
|
||||
string c_print(const vector<string>& args, const vector<string>& _) const {
|
||||
if (args.empty()) { return "0.0"; }
|
||||
|
||||
ostringstream os;
|
||||
os << "(" << args[0];
|
||||
for (unsigned i = 1; i < args.size(); ++i) {
|
||||
os << "+" << args[i];
|
||||
}
|
||||
os << ")";
|
||||
return os.str();
|
||||
}
|
||||
|
||||
Interval eval(const vector<Interval>& args, const vector<Interval>& inputs) const {
|
||||
Interval interv(0.0);
|
||||
for (unsigned i = 0; i < args.size(); ++i) {
|
||||
interv += args[i];
|
||||
}
|
||||
return interv;
|
||||
}
|
||||
|
||||
unsigned min_arity() const { return 0; }
|
||||
bool has_varargs() const { return true; }
|
||||
|
||||
string name() const { return "sum"; }
|
||||
};
|
||||
|
||||
|
||||
class Prod : public FunDef {
|
||||
|
||||
public :
|
||||
|
||||
double eval(const vector<double>& vals, const vector<double>& _) const {
|
||||
double res = 1;
|
||||
for (unsigned i = 0; i < vals.size(); ++i) res *= vals[i];
|
||||
return res;
|
||||
}
|
||||
|
||||
string c_print(const vector<string>& args, const vector<string>& _) const {
|
||||
if (args.empty()) { return "1.0"; }
|
||||
|
||||
ostringstream os;
|
||||
os << "(" << args[0];
|
||||
for (unsigned i = 1; i < args.size(); ++i) {
|
||||
os << "*" << args[i];
|
||||
}
|
||||
os << ")";
|
||||
|
||||
return os.str();
|
||||
}
|
||||
|
||||
Interval eval(const vector<Interval>& args, const vector<Interval>& inputs) const {
|
||||
Interval interv(1.0);
|
||||
for (unsigned i = 0; i < args.size(); ++i) {
|
||||
interv *= args[i];
|
||||
}
|
||||
return interv;
|
||||
}
|
||||
|
||||
unsigned min_arity() const { return 0; }
|
||||
bool has_varargs() const { return true; }
|
||||
|
||||
string name() const { return "prod"; }
|
||||
};
|
||||
|
||||
|
||||
class Power : public FunDef {
|
||||
public :
|
||||
double eval(const vector<double>& vals, const vector<double>& _) const {
|
||||
return pow(vals[0], vals[1]);
|
||||
}
|
||||
|
||||
string c_print(const vector<string>& args, const vector<string>& _) const {
|
||||
return "pow(" + args[0] + ',' + args[1] + ')';
|
||||
}
|
||||
|
||||
Interval eval(const vector<Interval>& args, const vector<Interval>& _) const {
|
||||
Interval first = args[0];
|
||||
Interval second = args[1];
|
||||
Interval lg = log(first);
|
||||
if (!valid(lg)) throw interval_error();
|
||||
return exp(second * lg);
|
||||
}
|
||||
|
||||
unsigned min_arity() const { return 2; }
|
||||
|
||||
string name() const { return "pow"; }
|
||||
};
|
||||
|
||||
class IsNeg : public FunDef {
|
||||
|
||||
public:
|
||||
double eval(const vector<double>& vals, const vector<double>& _) const {
|
||||
if (vals[0] < 0.0) return vals[1];
|
||||
return vals[2];
|
||||
}
|
||||
|
||||
double eval(const Sym& sym, const vector<double>& inputs) const {
|
||||
const SymVec& args = sym.args();
|
||||
double arg0 = ::eval(args[0], inputs);
|
||||
if (arg0 < 0.0) {
|
||||
return ::eval(args[1], inputs);
|
||||
}
|
||||
return ::eval(args[2], inputs);
|
||||
}
|
||||
|
||||
string c_print(const vector<string>& args, const vector<string>& _) const {
|
||||
return "((" + args[0] + "<0.0)?" + args[1] + ":" + args[2]+")";
|
||||
}
|
||||
|
||||
Interval eval(const vector<Interval>& args, const vector<Interval>& _) const {
|
||||
Interval a0 = args[0];
|
||||
if (a0.upper() < 0.0) return args[1];
|
||||
if (a0.lower() >= 0.0) return args[2];
|
||||
|
||||
return Interval( std::min(args[1].lower(), args[2].lower()), std::max(args[1].upper(), args[2].upper()));
|
||||
}
|
||||
|
||||
unsigned min_arity() const { return 3; }
|
||||
|
||||
string name() const { return "ifltz"; }
|
||||
};
|
||||
|
||||
template <typename Func>
|
||||
class Unary : public FunDef {
|
||||
|
||||
Func un;
|
||||
|
||||
double eval(const vector<double>& vals, const vector<double>& _) const {
|
||||
return un(vals[0]);
|
||||
}
|
||||
|
||||
string c_print(const vector<string>& args, const vector<string>& _) const {
|
||||
return un(args[0]);
|
||||
}
|
||||
|
||||
Interval eval(const vector<Interval>& args, const vector<Interval>& _) const {
|
||||
return un(args[0]);
|
||||
}
|
||||
|
||||
unsigned min_arity() const { return 1; }
|
||||
|
||||
string name() const { return un.name(); }
|
||||
|
||||
};
|
||||
|
||||
struct Inv {
|
||||
double operator()(double val) const { return 1.0 / val; }
|
||||
string operator()(string v) const { return "(1./" + v + ")"; }
|
||||
Interval operator()(Interval v) const { return 1.0 / v; }
|
||||
|
||||
string name() const { return "inv"; }
|
||||
};
|
||||
|
||||
struct Min {
|
||||
double operator()(double val) const { return -val; }
|
||||
string operator()(string v) const { return "(-" + v + ")"; }
|
||||
Interval operator()(Interval v) const { return -v; }
|
||||
|
||||
string name() const { return "min"; }
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
string prototypes = "double pow(double, double);";
|
||||
string get_prototypes() { return prototypes; }
|
||||
unsigned add_prototype(string str) { prototypes += string("double ") + str + "(double);"; return prototypes.size(); }
|
||||
|
||||
token_t add_function(FunDef* function, token_t where) {
|
||||
if (language.size() <= where) language.resize(where+1);
|
||||
language[where] = function;
|
||||
return 0;
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
#define FUNCDEF(funcname) struct funcname##_struct { \
|
||||
double operator()(double val) const { return funcname(val); }\
|
||||
string operator()(string val) const { return string(#funcname) + '(' + val + ')'; }\
|
||||
Interval operator()(Interval val) const { return funcname(val); }\
|
||||
string name() const { return string(#funcname); }\
|
||||
};\
|
||||
static const token_t funcname##_token_static = add_function( new Unary<funcname##_struct>, funcname##_token);\
|
||||
unsigned funcname##_size = add_prototype(#funcname);
|
||||
|
||||
static token_t ssum_token = add_function( new Sum , sum_token);
|
||||
static token_t sprod_token = add_function( new Prod, prod_token);
|
||||
static token_t sinv_token = add_function( new Unary<Inv>, inv_token);
|
||||
static token_t smin_token = add_function( new Unary<Min>, min_token);
|
||||
static token_t spow_token = add_function( new Power, pow_token);
|
||||
static token_t sifltz_token = add_function( new IsNeg, ifltz_token);
|
||||
|
||||
FUNCDEF(sin);
|
||||
FUNCDEF(cos);
|
||||
FUNCDEF(tan);
|
||||
FUNCDEF(asin);
|
||||
FUNCDEF(acos);
|
||||
FUNCDEF(atan);
|
||||
|
||||
FUNCDEF(sinh);
|
||||
FUNCDEF(cosh);
|
||||
FUNCDEF(tanh);
|
||||
FUNCDEF(asinh);
|
||||
FUNCDEF(acosh);
|
||||
FUNCDEF(atanh);
|
||||
|
||||
FUNCDEF(exp);
|
||||
FUNCDEF(log);
|
||||
} // namespace
|
||||
|
||||
double sqr(double x) { return x*x; }
|
||||
|
||||
namespace {
|
||||
FUNCDEF(sqr);
|
||||
FUNCDEF(sqrt);
|
||||
|
||||
const int buildInFunctionOffset = language.size();
|
||||
} // namespace
|
||||
|
||||
void add_tokens() {
|
||||
unsigned sz = language.size();
|
||||
language.resize(sz + sz+1); // double
|
||||
|
||||
for (unsigned i = sz; i < language.size(); ++i) {
|
||||
free_list.push_back(i);
|
||||
}
|
||||
}
|
||||
|
||||
void extend_free_list() {
|
||||
// first check if we can clean up unused tokens;
|
||||
const vector<unsigned>& refcount = Sym::token_refcount();
|
||||
for (unsigned i = buildInFunctionOffset; i < refcount.size(); ++i) {
|
||||
if (language[i] == 0) continue;
|
||||
|
||||
bool c = is_constant(i);
|
||||
bool l = is_lambda(i);
|
||||
|
||||
if (refcount[i] == 0 && (c || l)) {
|
||||
|
||||
if (c) {
|
||||
doubleSet.erase(token_value[i]);
|
||||
}
|
||||
|
||||
if (l) {
|
||||
lambdaSet.erase(token_lambda[i]);
|
||||
}
|
||||
|
||||
delete language[i];
|
||||
language[i] = 0;
|
||||
free_list.push_back(i);
|
||||
}
|
||||
}
|
||||
|
||||
// if still empty, add new tokens
|
||||
if (free_list.empty()) {
|
||||
add_tokens();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Serialization */
|
||||
void write_raw(ostream& os, const Sym& sym) {
|
||||
token_t token = sym.token();
|
||||
const SymVec& args = sym.args();
|
||||
|
||||
if (is_constant(token)) {
|
||||
os << "c" << language[token]->c_print(vector<string>(), vector<string>());
|
||||
} else {
|
||||
|
||||
const Var* var = dynamic_cast<const Var*>( language[token] );
|
||||
|
||||
if (var != 0) {
|
||||
os << "v" << var->idx;
|
||||
} else {
|
||||
os << "f" << token << ' ' << args.size();
|
||||
}
|
||||
}
|
||||
|
||||
for (unsigned i = 0; i < args.size(); ++i) {
|
||||
write_raw(os, args[i]);
|
||||
}
|
||||
}
|
||||
|
||||
string write_raw(const Sym& sym) {
|
||||
|
||||
ostringstream os;
|
||||
write_raw(os, sym);
|
||||
|
||||
return os.str();
|
||||
}
|
||||
|
||||
Sym read_raw(istream& is) {
|
||||
char id = is.get();
|
||||
|
||||
switch (id) {
|
||||
case 'c' :
|
||||
{
|
||||
double val;
|
||||
is.get(); // skip '('
|
||||
is >> val;
|
||||
is.get(); // skip ')'
|
||||
return SymConst(val);
|
||||
}
|
||||
case 'v' :
|
||||
{
|
||||
unsigned idx;
|
||||
is >> idx;
|
||||
return SymVar(idx);
|
||||
}
|
||||
case 'f' :
|
||||
{
|
||||
token_t token;
|
||||
unsigned arity;
|
||||
is >> token;
|
||||
is >> arity;
|
||||
SymVec args(arity);
|
||||
for (unsigned i = 0; i < arity; ++i) {
|
||||
args[i] = read_raw(is);
|
||||
}
|
||||
|
||||
return Sym(token, args);
|
||||
}
|
||||
default : {
|
||||
cerr << "Character = " << id << " Could not read formula from stream" << endl;
|
||||
exit(1);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return Sym();
|
||||
}
|
||||
|
||||
Sym read_raw(string str) {
|
||||
istringstream is(str);
|
||||
return read_raw(is);
|
||||
}
|
||||
|
||||
void read_raw(istream& is, Sym& sym) {
|
||||
sym = read_raw(is);
|
||||
}
|
||||
|
||||
186
deprecated/eo/contrib/mathsym/fun/FunDef.h
Normal file
186
deprecated/eo/contrib/mathsym/fun/FunDef.h
Normal file
|
|
@ -0,0 +1,186 @@
|
|||
/*
|
||||
* Copyright (C) 2005 Maarten Keijzer
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of version 2 of the GNU General Public License as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This program 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 this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef FUNCTION_DEF_H_
|
||||
#define FUNCTION_DEF_H_
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <memory>
|
||||
#include <iostream>
|
||||
|
||||
#include "sym/Sym.h"
|
||||
#include "eval/Interval.h"
|
||||
|
||||
class FunDef {
|
||||
public:
|
||||
|
||||
virtual ~FunDef() {}
|
||||
|
||||
// (possibly) lazy evaluation function, default implementation calls 'eager' eval
|
||||
virtual double eval(const SymVec& args, const std::vector<double>& inputs) const;
|
||||
|
||||
// eager evaluation function
|
||||
virtual double eval(const std::vector<double>& args, const std::vector<double>& inputs) const = 0;
|
||||
|
||||
// interval evaluation
|
||||
virtual Interval eval(const std::vector<Interval>& args, const std::vector<Interval>& inputs) const = 0;
|
||||
|
||||
// prints 'c' like code
|
||||
virtual std::string c_print(const std::vector<std::string>& names, const std::vector<std::string>& names) const = 0;
|
||||
|
||||
virtual unsigned min_arity() const = 0;
|
||||
virtual bool has_varargs() const { return false; } // sum, prod, min, max are variable arity
|
||||
|
||||
virtual std::string name() const = 0;
|
||||
|
||||
protected:
|
||||
|
||||
};
|
||||
|
||||
/** Gets out all function that are defined (excluding constants and variables) */
|
||||
extern std::vector<const FunDef*> get_defined_functions();
|
||||
|
||||
/** Gets a specific function (including vars and constants) out */
|
||||
extern const FunDef& get_element(token_t token);
|
||||
|
||||
/** Single case evaluation */
|
||||
extern double eval(const Sym& sym, const std::vector<double>& inputs);
|
||||
|
||||
/** Static analysis through interval arithmetic */
|
||||
extern Interval eval(const Sym& sym, const std::vector<Interval>& inputs);
|
||||
|
||||
/** Pretty printers, second version allows setting of variable names */
|
||||
extern std::string c_print(const Sym& sym);
|
||||
|
||||
/** Pretty printers, allows setting of variable names */
|
||||
extern std::string c_print(const Sym& sym, const std::vector<std::string>& var_names);
|
||||
|
||||
/** Pretty printer streamer */
|
||||
inline std::ostream& operator<<(std::ostream& os, const Sym& sym) { return os << c_print(sym); }
|
||||
|
||||
/* Support for Ephemeral Random Constants (ERC) */
|
||||
|
||||
/** Create constant with this value, memory is managed. If reference count drops to zero value is deleted. */
|
||||
extern Sym SymConst(double value);
|
||||
/** Create variable */
|
||||
extern Sym SymVar(unsigned idx);
|
||||
|
||||
/** Create 'lambda expression;
|
||||
* This is a neutral operation. It will replace
|
||||
* all variables in the expression by arguments,
|
||||
* wrap the expression in a Lambda function
|
||||
* and returns a tree applying the lambda function
|
||||
* to the original variable.
|
||||
*
|
||||
* A call like SymLambda( SymVar(1) + SymVar(1) * 3.1) will result in
|
||||
* a Lambda function (a0 + a0 * 3.1) with one argument: SymVar(1)*/
|
||||
|
||||
extern Sym SymLambda(Sym expression);
|
||||
|
||||
extern Sym SymUnlambda(Sym sym);
|
||||
|
||||
/** Expands all lambda expressions inline */
|
||||
extern Sym expand_all(Sym sym);
|
||||
extern Sym compress(Sym sym);
|
||||
|
||||
/** Get out the values for all constants in the expression */
|
||||
std::vector<double> get_constants(Sym sym);
|
||||
|
||||
/** Set the values for all constants in the expression. Vector needs to be the same size as the one get_constants returns
|
||||
* The argument isn't touched, it will return a new sym with the constants set. */
|
||||
Sym set_constants(Sym sym, const std::vector<double>& constants);
|
||||
|
||||
/** check if a token is a constant */
|
||||
extern bool is_constant(token_t token);
|
||||
extern double get_constant_value(token_t token);
|
||||
/** check if a token is a variable */
|
||||
extern bool is_variable(token_t token);
|
||||
extern unsigned get_variable_index(token_t token);
|
||||
|
||||
/** check if a token is a user/automatically defined function */
|
||||
extern bool is_lambda(token_t token);
|
||||
|
||||
|
||||
/** simplifies a sym (sym_operations.cpp) Currently only simplifies constants */
|
||||
extern Sym simplify(Sym sym);
|
||||
|
||||
/** differentiates a sym to a token (sym_operations.cpp)
|
||||
* The token can be a variable or a constant
|
||||
*/
|
||||
extern Sym differentiate(Sym sym, token_t dx);
|
||||
struct differentiation_error{}; // thrown in case of ifltz
|
||||
|
||||
/* Add function to the language table (and take a guess at the arity) */
|
||||
class LanguageTable;
|
||||
extern void add_function_to_table(LanguageTable& table, token_t token);
|
||||
|
||||
enum {
|
||||
sum_token,
|
||||
prod_token,
|
||||
inv_token,
|
||||
min_token,
|
||||
pow_token,
|
||||
ifltz_token,
|
||||
sin_token, cos_token, tan_token,
|
||||
asin_token, acos_token, atan_token,
|
||||
sinh_token, cosh_token, tanh_token,
|
||||
acosh_token, asinh_token, atanh_token,
|
||||
exp_token, log_token,
|
||||
sqr_token, sqrt_token
|
||||
};
|
||||
|
||||
/* Defition of function overloads: for example, this define the function 'Sym sin(Sym)' */
|
||||
|
||||
#define HEADERFUNC(name) inline Sym name(Sym arg) { return Sym(name##_token, arg); }
|
||||
|
||||
/* This defines the tokens: sin_token, cos_token, etc. */
|
||||
HEADERFUNC(inv);
|
||||
HEADERFUNC(sin);
|
||||
HEADERFUNC(cos);
|
||||
HEADERFUNC(tan);
|
||||
HEADERFUNC(asin);
|
||||
HEADERFUNC(acos);
|
||||
HEADERFUNC(atan);
|
||||
|
||||
HEADERFUNC(sinh);
|
||||
HEADERFUNC(cosh);
|
||||
HEADERFUNC(tanh);
|
||||
HEADERFUNC(asinh);
|
||||
HEADERFUNC(acosh);
|
||||
HEADERFUNC(atanh);
|
||||
|
||||
HEADERFUNC(exp);
|
||||
HEADERFUNC(log);
|
||||
|
||||
HEADERFUNC(sqr);
|
||||
HEADERFUNC(sqrt);
|
||||
|
||||
/* Get the prototype functions out, this is needed for compilation */
|
||||
extern std::string get_prototypes();
|
||||
|
||||
// reading and writing in internal format, no parser for symbolic functions implemented yet
|
||||
extern std::string write_raw(const Sym& sym);
|
||||
extern void write_raw(std::ostream& os, const Sym& sym);
|
||||
extern Sym read_raw(std::string str);
|
||||
extern Sym read_raw(std::istream& is);
|
||||
extern void read_raw(std::istream& is, Sym& sym);
|
||||
|
||||
#include "SymOps.h"
|
||||
|
||||
#endif
|
||||
|
||||
109
deprecated/eo/contrib/mathsym/fun/SymOps.cpp
Normal file
109
deprecated/eo/contrib/mathsym/fun/SymOps.cpp
Normal file
|
|
@ -0,0 +1,109 @@
|
|||
/*
|
||||
* Copyright (C) 2005 Maarten Keijzer
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of version 2 of the GNU General Public License as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This program 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 this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "FunDef.h"
|
||||
#include "SymOps.h"
|
||||
#include "Sym.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
void collect(token_t t, Sym a, SymVec& args) {
|
||||
|
||||
if (a.token() == t) {
|
||||
const SymVec& a_args = a.args();
|
||||
for (unsigned i = 0; i < a_args.size(); ++i) {
|
||||
collect(t, a_args[i], args);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
args.push_back(a);
|
||||
}
|
||||
|
||||
Sym operator+(Sym a, Sym b) {
|
||||
|
||||
SymVec args;
|
||||
|
||||
collect(sum_token, a, args);
|
||||
collect(sum_token, b, args);
|
||||
|
||||
return Sym(sum_token, args);
|
||||
}
|
||||
|
||||
Sym operator*(Sym a, Sym b) {
|
||||
|
||||
SymVec args;
|
||||
|
||||
collect(prod_token, a, args);
|
||||
collect(prod_token, b, args);
|
||||
|
||||
return Sym(prod_token, args);
|
||||
}
|
||||
|
||||
Sym operator/(Sym a, Sym b) {
|
||||
|
||||
SymVec args;
|
||||
|
||||
collect(prod_token, a, args);
|
||||
|
||||
SymVec args2;
|
||||
collect(prod_token, b, args2);
|
||||
|
||||
SymVec inv;
|
||||
inv.push_back(Sym(prod_token, args2));
|
||||
|
||||
args.push_back( Sym(inv_token, inv) );
|
||||
|
||||
return Sym(prod_token, args);
|
||||
}
|
||||
|
||||
Sym operator-(Sym a, Sym b) {
|
||||
|
||||
SymVec args;
|
||||
|
||||
collect(sum_token, a, args);
|
||||
|
||||
SymVec args2;
|
||||
collect(sum_token, b, args2);
|
||||
|
||||
SymVec min;
|
||||
min.push_back(Sym(sum_token, args2));
|
||||
|
||||
args.push_back( Sym(min_token, min) );
|
||||
|
||||
return Sym(sum_token, args);
|
||||
}
|
||||
|
||||
Sym operator-(Sym a) {
|
||||
return Sym(min_token, a);
|
||||
}
|
||||
|
||||
Sym pow(Sym a, Sym b) {
|
||||
SymVec args;
|
||||
args.push_back(a);
|
||||
args.push_back(b);
|
||||
return Sym(pow_token, args);
|
||||
}
|
||||
|
||||
Sym ifltz(Sym a, Sym b, Sym c) {
|
||||
SymVec args;
|
||||
args.push_back(a);
|
||||
args.push_back(b);
|
||||
args.push_back(c);
|
||||
return Sym(ifltz_token, args);
|
||||
}
|
||||
|
||||
31
deprecated/eo/contrib/mathsym/fun/SymOps.h
Normal file
31
deprecated/eo/contrib/mathsym/fun/SymOps.h
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
/*
|
||||
* Copyright (C) 2005 Maarten Keijzer
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of version 2 of the GNU General Public License as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This program 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 this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef SYMOPS_H
|
||||
#define SYMOPS_H
|
||||
|
||||
#include "sym/Sym.h"
|
||||
|
||||
extern Sym operator+(Sym a, Sym b);
|
||||
extern Sym operator*(Sym a, Sym b);
|
||||
extern Sym operator/(Sym a, Sym b);
|
||||
extern Sym operator-(Sym a, Sym b);
|
||||
extern Sym pow(Sym a, Sym b);
|
||||
extern Sym ifltz(Sym a, Sym b, Sym c);
|
||||
extern Sym operator-(Sym a);
|
||||
|
||||
#endif
|
||||
174
deprecated/eo/contrib/mathsym/fun/sym_operations.cpp
Normal file
174
deprecated/eo/contrib/mathsym/fun/sym_operations.cpp
Normal file
|
|
@ -0,0 +1,174 @@
|
|||
/*
|
||||
* Copyright (C) 2005 Maarten Keijzer
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of version 2 of the GNU General Public License as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This program 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 this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include <FunDef.h>
|
||||
|
||||
using namespace std;
|
||||
|
||||
Sym simplify_constants(Sym sym) {
|
||||
|
||||
SymVec args = sym.args();
|
||||
token_t token = sym.token();
|
||||
|
||||
bool has_changed = false;
|
||||
bool all_constants = true;
|
||||
|
||||
for (unsigned i = 0; i < args.size(); ++i) {
|
||||
|
||||
Sym arg = simplify_constants(args[i]);
|
||||
|
||||
if (arg != args[i]) {
|
||||
has_changed = true;
|
||||
}
|
||||
args[i] = arg;
|
||||
|
||||
all_constants &= is_constant(args[i].token());
|
||||
}
|
||||
|
||||
if (args.size() == 0) {
|
||||
|
||||
if (sym.token() == sum_token) return SymConst(0.0);
|
||||
if (sym.token() == prod_token) return SymConst(1.0);
|
||||
|
||||
return sym; // variable or constant
|
||||
}
|
||||
|
||||
if (all_constants) {
|
||||
// evaluate
|
||||
|
||||
vector<double> dummy;
|
||||
|
||||
double v = ::eval(sym, dummy);
|
||||
|
||||
Sym result = SymConst(v);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
if (has_changed) {
|
||||
return Sym(token, args);
|
||||
}
|
||||
|
||||
return sym;
|
||||
|
||||
}
|
||||
|
||||
// currently only simplifies constants
|
||||
Sym simplify(Sym sym) {
|
||||
|
||||
return simplify_constants(sym);
|
||||
|
||||
}
|
||||
|
||||
Sym derivative(token_t token, Sym x) {
|
||||
Sym one = Sym(prod_token);
|
||||
|
||||
switch (token) {
|
||||
case inv_token : return Sym(inv_token, sqr(x));
|
||||
|
||||
case sin_token : return -cos(x);
|
||||
case cos_token : return sin(x);
|
||||
case tan_token : return one + sqr(tan(x));
|
||||
|
||||
case asin_token : return inv( sqrt(one - sqr(x)));
|
||||
case acos_token: return -inv( sqrt(one - sqr(x)));
|
||||
case atan_token : return inv( sqrt(one + sqr(x)));
|
||||
|
||||
case cosh_token : return -sinh(x);
|
||||
case sinh_token : return cosh(x);
|
||||
case tanh_token : return one - sqr( tanh(x) );
|
||||
|
||||
case asinh_token : return inv( sqrt( one + sqr(x) ));
|
||||
case acosh_token : return inv( sqrt(x-one) * sqrt(x + one) );
|
||||
case atanh_token : return inv(one - sqr(x));
|
||||
|
||||
case exp_token : return exp(x);
|
||||
case log_token : return inv(x);
|
||||
|
||||
case sqr_token : return SymConst(2.0) * x;
|
||||
case sqrt_token : return SymConst(0.5) * inv( sqrt(x));
|
||||
default :
|
||||
throw differentiation_error();
|
||||
}
|
||||
|
||||
return x;
|
||||
}
|
||||
|
||||
extern Sym differentiate(Sym sym, token_t dx) {
|
||||
|
||||
token_t token = sym.token();
|
||||
|
||||
Sym zero = Sym(sum_token);
|
||||
Sym one = Sym(prod_token);
|
||||
|
||||
if (token == dx) {
|
||||
return one;
|
||||
}
|
||||
|
||||
SymVec args = sym.args();
|
||||
|
||||
if (args.size() == 0) { // df/dx with f != x
|
||||
return zero;
|
||||
}
|
||||
|
||||
switch (token) {
|
||||
|
||||
case sum_token:
|
||||
{
|
||||
for (unsigned i = 0; i < args.size(); ++i) {
|
||||
args[i] = differentiate(args[i], dx);
|
||||
}
|
||||
|
||||
if (args.size() == 1) return args[0];
|
||||
return Sym(sum_token, args);
|
||||
}
|
||||
case min_token :
|
||||
{
|
||||
return -differentiate(args[0],dx);
|
||||
}
|
||||
case prod_token:
|
||||
{
|
||||
if (args.size() == 1) return differentiate(args[0], dx);
|
||||
|
||||
if (args.size() == 2) {
|
||||
return args[0] * differentiate(args[1], dx) + args[1] * differentiate(args[0], dx);
|
||||
}
|
||||
// else
|
||||
Sym c = args.back();
|
||||
args.pop_back();
|
||||
Sym f = Sym(prod_token, args);
|
||||
Sym df = differentiate( f, dx);
|
||||
|
||||
return c * df + f * differentiate(c,dx);
|
||||
}
|
||||
case pow_token :
|
||||
{
|
||||
return pow(args[0], args[1]) * args[1] * inv(args[0]);
|
||||
}
|
||||
case ifltz_token :
|
||||
{ // cannot be differentiated
|
||||
throw differentiation_error(); // TODO define proper exception
|
||||
}
|
||||
|
||||
default: // unary function: apply chain rule
|
||||
{
|
||||
Sym arg = args[0];
|
||||
return derivative(token, arg) * differentiate(arg, dx);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
27
deprecated/eo/contrib/mathsym/fun/util.cpp
Normal file
27
deprecated/eo/contrib/mathsym/fun/util.cpp
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
/*
|
||||
* Copyright (C) 2005 Maarten Keijzer
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of version 2 of the GNU General Public License as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This program 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 this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include <string>
|
||||
#include <iostream>
|
||||
|
||||
using namespace std;
|
||||
|
||||
double error(string errstr) {
|
||||
cerr << "ERROR: " << errstr << endl;
|
||||
exit(1);
|
||||
}
|
||||
|
||||
Loading…
Add table
Add a link
Reference in a new issue