FunDef.cpp

00001 /*          
00002  *             Copyright (C) 2005 Maarten Keijzer
00003  *
00004  *          This program is free software; you can redistribute it and/or modify
00005  *          it under the terms of version 2 of the GNU General Public License as 
00006  *          published by the Free Software Foundation. 
00007  *
00008  *          This program is distributed in the hope that it will be useful,
00009  *          but WITHOUT ANY WARRANTY; without even the implied warranty of
00010  *          MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00011  *          GNU General Public License for more details.
00012  *
00013  *          You should have received a copy of the GNU General Public License
00014  *          along with this program; if not, write to the Free Software
00015  *          Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00016  */
00017 
00018 
00019 #include <sstream>
00020 #include "Sym.h"
00021 #include "FunDef.h"
00022 #include <LanguageTable.h>
00023 
00024 using namespace std;
00025 using namespace boost::numeric;
00026 
00027 vector<const FunDef*> language; 
00028 
00029 token_t add_function(FunDef* function) { 
00030     language.push_back(function); 
00031     return token_t(language.size()-1); 
00032 }
00033 
00034 const FunDef& get_element(token_t token) { return *language[token]; }
00035 
00036 /* Printing */
00037 
00038 string c_print(const Sym& sym) {
00039     return c_print(sym, vector<string>());
00040 }
00041 
00042 string c_print(const Sym& sym, const vector<string>& vars) {
00043     const SymVec& args = sym.args();
00044     vector<string> names(args.size());
00045     for (unsigned i = 0; i < args.size(); ++i) {
00046         names[i] = c_print(args[i], vars);
00047     }
00048     return language[sym.token()]->c_print(names, vars);
00049 }
00050 
00051 /* Evaluation */
00052 
00053 
00054 double eval(const Sym& sym, const std::vector<double>& inputs) {
00055     return language[sym.token()]->eval(sym.args(), inputs);
00056 }
00057 
00058 
00059 /* Interval Logic */
00060 Interval eval(const Sym& sym, const vector<Interval>& inputs) {
00061     const SymVec& args = sym.args();
00062     vector<Interval> interv(args.size());
00063     for (unsigned i = 0; i < args.size(); ++i) {
00064         interv[i] = eval(args[i], inputs);
00065     
00066         if (!valid(interv[i])) throw interval_error();
00067     }
00068     return language[sym.token()]->eval(interv, inputs);
00069 }
00070 
00071 /*  */
00072 void add_function_to_table(LanguageTable& table, token_t token) {
00073     const FunDef& fundef = *language[token];
00074     
00075     if (fundef.has_varargs() == false) {
00076         table.add_function(token, fundef.min_arity());
00077     } else { // sum or prod (or min or max)
00078         table.add_function(token, 2);
00079     }
00080 }
00081 
00082 
00083 // by default it is eager
00084 double FunDef::eval(const SymVec& args, const vector<double>& inputs) const {
00085     vector<double> values(args.size());
00086     for (unsigned i = 0; i < args.size(); ++i) {
00087         values[i] = ::eval(args[i], inputs);
00088     }
00089 
00090     return eval(values, inputs);
00091 }
00092 
00093 /* Variable Handling */
00094 FunDef* make_var(int idx); // defined in FunDefs.h
00095 static vector<token_t> var_token;
00096 
00097 Sym SymVar(unsigned idx) {
00098     if (var_token.size() <= idx) {
00099         // it is new
00100         var_token.resize(idx+1, token_t(-1));
00101         var_token[idx] = add_function( make_var(idx) );
00102     } else if (var_token[idx] == token_t(-1)) {
00103         var_token[idx] = add_function( make_var(idx) );
00104     }
00105     return Sym(var_token[idx]);
00106 }
00107 
00108 
00109 /* Constant Handling */
00110 
00111 struct HashDouble{
00112     size_t operator()(double val) const {
00113         unsigned long h = 0;
00114         char* s = (char*)&val;
00115         for (unsigned i=0 ; i<sizeof(double); ++i)
00116             h = 5*h + s[i];
00117         return size_t(h);
00118     }
00119 };
00120 
00121 #if USE_TR1
00122 typedef std::tr1::unordered_map<double, token_t> DoubleSet;
00123 typedef std::tr1::unordered_map<Sym, token_t>    LambdaSet;
00124 #else
00125 typedef hash_map<double, token_t, HashDouble> DoubleSet;
00126 typedef hash_map<Sym, token_t, HashSym> LambdaSet;
00127 #endif
00128 
00129 static DoubleSet doubleSet; // for quick checking if a constant already exists
00130 static vector<double> token_value;
00131 
00132 static LambdaSet lambdaSet;
00133 static vector<Sym> token_lambda;
00134 
00135 static std::vector<token_t> free_list;
00136 
00137 void delete_val(token_t token) { // clean up the information about this value
00138      
00139     if (is_constant(token)) {
00140         //cout << "Deleting constant token " << token << endl;
00141         double value = token_value[token];
00142         doubleSet.erase(value);
00143         
00144         delete language[token];
00145         language[token] = 0;
00146         free_list.push_back(token);
00147     }
00148     else if (is_lambda(token)) {
00149         //cout << "Deleting lambda token " << token << endl;
00150         
00151         Sym expression = token_lambda[token];
00152         lambdaSet.erase(expression);
00153         
00154         delete language[token];
00155         language[token] = 0;
00156         free_list.push_back(token);
00157     }
00158 }
00159 
00160 
00161 FunDef* make_const(double value);
00162 
00163 void extend_free_list();
00164 
00165 Sym SymConst(double value) { 
00166    
00167     DoubleSet::iterator it = doubleSet.find(value);
00168     
00169     if (it != doubleSet.end()) {
00170         return Sym(it->second); // already exists
00171     }
00172        
00173     
00174     if (free_list.empty()) { // make space for tokens;
00175         extend_free_list();
00176     }
00177 
00178     token_t token = free_list.back();
00179     free_list.pop_back();
00180     //cout << "Creating constant with token " << token << endl; 
00181     assert(language[token] == 0);
00182     
00183     language[token] = make_const(value);
00184     
00185     doubleSet[value] = token;
00186     if (token_value.size() < token) token_value.resize(token+1);
00187     token_value[token] = value;
00188     
00189     return Sym(token);
00190 }
00191 
00192 /* LanguageTable depends on this one, XXX move somewhere safe.*/
00193 #include <utils/eoRNG.h>
00194 extern Sym default_const() { return SymConst(rng.normal()); }
00195 
00196 /* The functions */
00197 namespace {
00198 
00199 class Var : public FunDef {
00200     public :
00201         unsigned idx;
00202         string default_str;
00203 
00204         Var(unsigned _idx) : idx(_idx) {
00205             ostringstream os;
00206             os << "x[" << idx << ']'; // CompiledCode expects this form
00207             default_str = os.str();
00208         }
00209         
00210         double eval(const vector<double>& _, const vector<double>& inputs) const { return inputs[idx]; }
00211         double eval(const SymVec& _, const vector<double>& inputs) const { return inputs[idx]; }
00212         string c_print(const vector<string>& _, const vector<string>& names) const { 
00213             if (names.empty()) {
00214                 return default_str;
00215             }
00216             return names[idx]; 
00217         }
00218 
00219         Interval eval(const vector<Interval>& _, const vector<Interval>& inputs) const { 
00220             return inputs[idx]; 
00221         }
00222         
00223         unsigned min_arity() const { return 0; }
00224 
00225         string name() const { return "var"; }
00226         
00227 };
00228 
00229 class Const : public FunDef {
00230     public:
00231         double value;
00232         string value_str;
00233         
00234         Const(double _value) : value(_value) {
00235             ostringstream os;
00236             os.precision(17);
00237             os.setf(ios::showpoint);
00238             os << '(' << value << ')';
00239             value_str = os.str();       
00240         }
00241 
00242 
00243         double eval(const vector<double>& _, const vector<double>& inputs) const { return value; }
00244         double eval(const SymVec& _, const vector<double>& inputs) const { return value; }
00245         string c_print(const vector<string>& _, const vector<string>& names) const { 
00246             return value_str; 
00247         }
00248         
00249         Interval eval(const vector<Interval>& _, const vector<Interval>& inputs) const { 
00250             // Profil/Bias seems to have a problem with 0 * inf when the Interval is exact zero (fpe)
00251             //if (value == 0.0) return Interval(-BiasEpsilon,BiasEpsilon);
00252             return Interval(value); 
00253         }
00254 
00255         unsigned min_arity() const { return 0; }
00256 
00257         string name() const { return "parameter"; }
00258 };
00259 
00260 } // namespace 
00261     
00262 void get_constants(Sym sym, vector<double>& ret) {
00263     token_t token = sym.token();
00264     if (is_constant(token)) {
00265         double val = static_cast<const Const*>(language[token])->value;
00266         ret.push_back(val);
00267     }
00268 
00269     const SymVec& args = sym.args();
00270     for (unsigned i = 0; i < args.size(); ++i) {
00271          get_constants(args[i], ret);
00272     }
00273     
00274 }
00275 
00276 double get_constant_value(token_t token) {
00277     return static_cast<const Const*>(language[token])->value;
00278 }
00279 
00281 vector<double> get_constants(Sym sym) {
00282     vector<double> retval;
00283     get_constants(sym, retval);
00284     return retval;
00285 }
00286 
00289 Sym set_constants(Sym sym, vector<double>::const_iterator& it) {
00290     
00291     token_t token = sym.token();
00292     if (is_constant(token)) {
00293         return SymConst(*it++);
00294     }
00295 
00296     SymVec args = sym.args();
00297     for (unsigned i = 0; i < args.size(); ++i) {
00298          args[i] = set_constants(args[i], it);
00299     }
00300     
00301     return Sym(token, args);
00302 }
00303 
00304 Sym set_constants(Sym sym, const vector<double>& constants) {
00305     vector<double>::const_iterator it = constants.begin();
00306     return set_constants(sym, it);
00307 }
00308 
00309 // Get functions out, excluding Const and Var
00310 vector<const FunDef*> get_defined_functions() {
00311     vector<const FunDef*> res;
00312     for (unsigned i = 0; i < language.size(); ++i) {
00313         res.push_back(language[i]);
00314 
00315         if (is_constant(i) || is_variable(i)) {
00316             res.back() = 0; // erase
00317         }
00318     }
00319 
00320     return res;
00321 }
00322 
00323 FunDef* make_var(int idx) { return new Var(idx); }
00324 FunDef* make_const(double value) { return new Const(value); }
00325 
00326 bool is_constant(token_t token) {
00327     const Const* cnst = dynamic_cast<const Const*>( language[token] );
00328     return cnst != 0;
00329 }
00330 
00331 bool is_variable(token_t token) {
00332     const Var* var = dynamic_cast<const Var*>( language[token] );
00333     return var != 0;
00334 }
00335 
00336 unsigned get_variable_index(token_t token) {
00337     const Var* var = static_cast<const Var*>( language[token] );
00338     return var->idx;
00339 }
00340 
00341 namespace {
00342 class Lambda : public FunDef {
00343     public:
00344         Sym expression;
00345         int arity;
00346     
00347         Lambda(Sym expr, int arity_) : expression(expr), arity(arity_) {}
00348         
00349         double eval(const vector<double>& vals, const vector<double>& _) const {
00350             return ::eval(expression, vals); 
00351         }
00352         
00353         string c_print(const vector<string>& args, const vector<string>& _) const {
00354             return string("/*f*/") + ::c_print(expression, args) + string("/*eof*/");
00355         }
00356         
00357         Interval eval(const vector<Interval>& args, const vector<Interval>& _) const { 
00358             return ::eval(expression, args);
00359         }
00360 
00361         unsigned min_arity() const { return arity; }
00362         string name() const { return "F"; }
00363         
00364 };
00365     Sym normalize(Sym sym, SymVec& args) {
00366         // check if it's a variable
00367         token_t token = sym.token();
00368         const Var* var = dynamic_cast< const Var*>(language[token]);
00369     
00370         if (var != 0) {
00371             for (unsigned i = 0; i < args.size(); ++i) {
00372                 if (sym == args[i]) {
00373                     return SymVar(i); // replace with reference to arg
00374                 }
00375             }
00376 
00377             // not replaced, add it
00378             args.push_back(sym);
00379             return SymVar(args.size()-1);
00380             
00381         }
00382         
00383         SymVec a = sym.args();
00384         for (unsigned i = 0; i < a.size(); ++i) {
00385             a[i] = normalize(a[i], args);
00386         }
00387         
00388         return Sym(token, a);
00389     }
00390 }
00391 
00392 bool is_lambda(token_t token) {
00393     const Lambda* lambda = dynamic_cast<const Lambda*>( language[token]); 
00394     return lambda != 0;
00395 }
00396 
00397 std::ostream& print_list(Sym sym, ostream& os) {
00398     os << sym.token() << ' ';
00399     
00400     const SymVec& args = sym.args();
00401     for (unsigned i = 0; i < args.size(); ++i) {
00402         print_list(args[i], os);
00403     }
00404     return os;
00405 }
00406 
00407 token_t new_lambda(Sym sym, int arity) {
00408     // check if already present
00409 
00410     LambdaSet::iterator it = lambdaSet.find(sym);
00411     if (it != lambdaSet.end()) {
00412         return it->second;
00413     }
00414 
00415     
00416     // new, insert
00417     Lambda* lambda = new Lambda(sym, arity);
00418 
00419     if (free_list.empty()) {
00420         extend_free_list();
00421     }
00422     
00423     token_t token = free_list.back();
00424     free_list.pop_back();
00425     language[token] = lambda;
00426     
00427     lambdaSet[sym] = token;
00428     if (token_lambda.size() <= token) token_lambda.resize(token+1);
00429     token_lambda[token] = sym;
00430     
00431     return token;
00432 }
00433 
00434 /* Compression */
00435 typedef hash_map<Sym, unsigned, HashSym> OccMap;
00436 
00437 void count_occurances(Sym sym, OccMap& occ) {
00438     occ[sym]++;
00439     const SymVec& args = sym.args();
00440     for (unsigned i = 0; i < args.size(); ++i) {
00441         count_occurances(args[i], occ);
00442     }
00443 }
00444 
00445 Sym create_lambda(Sym sym, OccMap& occ, unsigned nvars, vector<Sym>& args) {
00446     unsigned o = occ[sym];
00447     unsigned sz = sym.size();
00448 
00449     if (o * sz > o + sz + nvars || is_variable(sym.token()) ) {
00450         // check if it's already present
00451         for (unsigned i = 0; i < args.size(); ++i) {
00452             if (args[i] == sym) {
00453                 return SymVar(i);
00454             }
00455         }
00456         // push_back
00457         args.push_back(sym);
00458         return SymVar(args.size()-1);
00459     }
00460     
00461     SymVec sym_args = sym.args();
00462     for (unsigned i = 0; i < sym_args.size(); ++i) {
00463         sym_args[i] = create_lambda(sym_args[i], occ, nvars, args);
00464     }
00465 
00466     return Sym(sym.token(), sym_args);
00467     
00468 }
00469 
00470 Sym compress(Sym sym) { 
00471     OccMap occ(sym.size());
00472     count_occurances(sym, occ);
00473 
00474     unsigned nvars = 0;
00475     for (OccMap::iterator it = occ.begin(); it != occ.end(); ++it) {
00476         if (is_variable(it->first.token())) nvars++;
00477     }
00478     
00479     SymVec args;
00480     Sym body = create_lambda(sym, occ, nvars, args);
00481     
00482     
00483     if (body.size() < sym.size()) {
00484         // see if the body can be compressed some more
00485         body = compress(body);
00486                 
00487         token_t token = new_lambda(body, args.size());
00488         
00489         for (unsigned i = 0; i < args.size(); ++i) {
00490             args[i] = compress(args[i]);
00491         }
00492 
00493         Sym result = Sym(token, args);
00494         return compress(result); // see if it can be compressed some more
00495     }
00496     
00497     return sym; 
00498 }
00499 
00500 Sym SymLambda(Sym expr) { return compress(expr); }
00501 
00502 Sym expand(Sym expr, const SymVec& args) {
00503     
00504     const Var* var = dynamic_cast<const Var*>( language[expr.token()] );
00505     if (var != 0) {
00506         return args[var->idx];
00507     }
00508 
00509     SymVec expr_args = expr.args();
00510     for (unsigned i = 0; i < expr_args.size(); ++i) {
00511         expr_args[i] = expand(expr_args[i], args);
00512     }
00513     
00514     return Sym(expr.token(), expr_args);
00515 }
00516 
00517 Sym SymUnlambda(Sym sym) {
00518     Sym retval = sym;
00519     const Lambda* lambda = dynamic_cast<const Lambda*>( language[sym.token()] );
00520     if (lambda != 0) {
00521         retval = expand(lambda->expression, sym.args());
00522     }
00523 
00524     return retval;
00525 }
00526 
00527 Sym expand_all(Sym sym) {
00528     SymVec args = sym.args();
00529     for (unsigned i = 0; i < args.size(); ++i) {
00530         args[i] = expand_all(args[i]);
00531     }
00532     
00533     Sym nw = SymUnlambda( Sym(sym.token(), args) ); 
00534     
00535     if (nw != sym) {
00536         nw = expand_all(nw);
00537     }
00538     
00539     return nw;
00540 }
00541 
00542 namespace {
00543 
00544 class Sum : public FunDef {
00545 
00546     public :
00547         
00548         double eval(const vector<double>& vals, const vector<double>& _) const { 
00549             double res = 0;
00550             for (unsigned i = 0; i < vals.size(); ++i) res += vals[i];
00551             return res;
00552         }
00553         
00554         string c_print(const vector<string>& args, const vector<string>& _) const { 
00555             if (args.empty()) { return "0.0"; }
00556             
00557             ostringstream os;
00558             os << "(" << args[0];
00559             for (unsigned i = 1; i < args.size(); ++i) {
00560                 os << "+" << args[i];
00561             }
00562             os << ")";
00563             return os.str();
00564         }
00565         
00566         Interval eval(const vector<Interval>& args, const vector<Interval>& inputs) const { 
00567             Interval interv(0.0); 
00568             for (unsigned i = 0; i < args.size(); ++i) {
00569                 interv += args[i];
00570             }
00571             return interv;
00572         }
00573 
00574         unsigned min_arity() const { return 0; }
00575         bool has_varargs() const { return true; }
00576 
00577         string name() const { return "sum"; }
00578 };
00579 
00580 
00581 class Prod : public FunDef {
00582 
00583     public :
00584         
00585         double eval(const vector<double>& vals, const vector<double>& _) const { 
00586             double res = 1;
00587             for (unsigned i = 0; i < vals.size(); ++i) res *= vals[i];
00588             return res;
00589         }
00590         
00591         string c_print(const vector<string>& args, const vector<string>& _) const { 
00592             if (args.empty()) { return "1.0"; }
00593             
00594             ostringstream os;
00595             os << "(" << args[0];
00596             for (unsigned i = 1; i < args.size(); ++i) {
00597                 os << "*" << args[i];
00598             }
00599             os << ")"; 
00600 
00601             return os.str();
00602         }
00603         
00604         Interval eval(const vector<Interval>& args, const vector<Interval>& inputs) const { 
00605             Interval interv(1.0);
00606             for (unsigned i = 0; i < args.size(); ++i) {
00607                 interv *= args[i];
00608             }
00609             return interv;
00610         }
00611 
00612         unsigned min_arity() const { return 0; }
00613         bool has_varargs() const { return true; }
00614 
00615         string name() const { return "prod"; }
00616 };
00617 
00618 
00619 class Power : public FunDef {
00620     public :
00621         double eval(const vector<double>& vals, const vector<double>& _) const {
00622             return pow(vals[0], vals[1]);
00623         }
00624 
00625         string c_print(const vector<string>& args, const vector<string>& _) const {
00626             return "pow(" + args[0] + ',' + args[1] + ')';
00627         }
00628 
00629         Interval eval(const vector<Interval>& args, const vector<Interval>& _) const {
00630             Interval first = args[0];
00631             Interval second = args[1];
00632             Interval lg = log(first);
00633             if (!valid(lg)) throw interval_error();
00634             return exp(second * lg); 
00635         }
00636 
00637         unsigned min_arity() const { return 2; }
00638 
00639         string name() const { return "pow"; }
00640 };
00641 
00642 class IsNeg : public FunDef {
00643 
00644     public:
00645         double eval(const vector<double>& vals, const vector<double>& _) const {
00646             if (vals[0] < 0.0) return vals[1];
00647             return vals[2];
00648         }
00649 
00650         double eval(const Sym& sym, const vector<double>& inputs) const {
00651             const SymVec& args = sym.args();
00652             double arg0 = ::eval(args[0], inputs);
00653             if (arg0 < 0.0) {
00654                 return ::eval(args[1], inputs);
00655             }
00656             return ::eval(args[2], inputs);
00657         }
00658 
00659         string c_print(const vector<string>& args, const vector<string>& _) const {
00660             return "((" + args[0] + "<0.0)?" + args[1] + ":" + args[2]+")";
00661         }
00662         
00663         Interval eval(const vector<Interval>& args, const vector<Interval>& _) const {
00664             Interval a0 = args[0];
00665             if (a0.upper() < 0.0) return args[1]; 
00666             if (a0.lower() >= 0.0) return args[2];
00667 
00668             return Interval( std::min(args[1].lower(), args[2].lower()), std::max(args[1].upper(), args[2].upper()));
00669         }
00670 
00671         unsigned min_arity() const { return 3; }
00672 
00673         string name() const { return "ifltz"; }
00674 };
00675 
00676 template <typename Func>
00677 class Unary : public FunDef {
00678     
00679     Func un;
00680     
00681     double eval(const vector<double>& vals, const vector<double>& _) const { 
00682         return un(vals[0]);     
00683     }
00684 
00685     string c_print(const vector<string>& args, const vector<string>& _) const { 
00686         return un(args[0]);
00687     }
00688 
00689     Interval eval(const vector<Interval>& args, const vector<Interval>& _) const {
00690         return un(args[0]);
00691     }
00692     
00693     unsigned min_arity() const { return 1; }
00694 
00695     string name() const { return un.name(); }
00696     
00697 };
00698 
00699 struct Inv {
00700     double operator()(double val) const { return 1.0 / val; }
00701     string operator()(string v)   const { return "(1./" + v + ")"; }
00702     Interval operator()(Interval v) const { return 1.0 / v; }
00703     
00704     string name() const { return "inv"; }
00705 };
00706 
00707 struct Min {
00708     double operator()(double val) const { return -val; }
00709     string operator()(string v) const   { return "(-" + v + ")"; }
00710     Interval operator()(Interval v) const { return -v; }
00711 
00712     string name() const { return "min"; }
00713 };
00714 
00715 } // namespace
00716 
00717 string prototypes = "double pow(double, double);";
00718 string get_prototypes() { return prototypes; }
00719 unsigned add_prototype(string str) { prototypes += string("double ") + str + "(double);"; return prototypes.size(); }
00720 
00721 token_t add_function(FunDef* function, token_t where) {
00722     if (language.size() <= where) language.resize(where+1);
00723     language[where] = function;
00724     return 0;
00725 }
00726 
00727 namespace {
00728 
00729 #define FUNCDEF(funcname) struct funcname##_struct { \
00730     double operator()(double val) const { return funcname(val); }\
00731     string operator()(string val) const  { return string(#funcname) + '(' + val + ')'; }\
00732     Interval operator()(Interval val) const { return funcname(val); }\
00733     string name() const { return string(#funcname); }\
00734 };\
00735 static const token_t funcname##_token_static = add_function( new Unary<funcname##_struct>, funcname##_token);\
00736 unsigned funcname##_size = add_prototype(#funcname);
00737 
00738 static token_t ssum_token  = add_function( new Sum , sum_token);
00739 static token_t sprod_token = add_function( new Prod, prod_token);
00740 static token_t sinv_token  = add_function( new Unary<Inv>, inv_token);
00741 static token_t smin_token  = add_function( new Unary<Min>, min_token);
00742 static token_t spow_token  = add_function( new Power, pow_token);
00743 static token_t sifltz_token = add_function( new IsNeg, ifltz_token);
00744 
00745 FUNCDEF(sin);
00746 FUNCDEF(cos);
00747 FUNCDEF(tan);
00748 FUNCDEF(asin);
00749 FUNCDEF(acos);
00750 FUNCDEF(atan);
00751 
00752 FUNCDEF(sinh);
00753 FUNCDEF(cosh);
00754 FUNCDEF(tanh);
00755 FUNCDEF(asinh);
00756 FUNCDEF(acosh);
00757 FUNCDEF(atanh);
00758 
00759 FUNCDEF(exp);
00760 FUNCDEF(log);
00761 } // namespace
00762 
00763 double sqr(double x) { return x*x; }
00764 
00765 namespace {
00766 FUNCDEF(sqr);
00767 FUNCDEF(sqrt);
00768 
00769 const int buildInFunctionOffset = language.size();
00770 } // namespace 
00771 
00772 void add_tokens() {
00773     unsigned sz = language.size();
00774     language.resize(sz + sz+1); // double
00775     
00776     for (unsigned i = sz; i < language.size(); ++i) {
00777        free_list.push_back(i); 
00778     }
00779 }
00780 
00781 void extend_free_list() {
00782     // first check if we can clean up unused tokens;
00783     const vector<unsigned>& refcount = Sym::token_refcount();
00784     for (unsigned i = buildInFunctionOffset; i < refcount.size(); ++i) {
00785         if (language[i] == 0) continue;
00786         
00787         bool c = is_constant(i);
00788         bool l = is_lambda(i);
00789         
00790         if (refcount[i] == 0 && (c || l)) {
00791             
00792             if (c) {
00793                 doubleSet.erase(token_value[i]);
00794             }
00795 
00796             if (l) {
00797                 lambdaSet.erase(token_lambda[i]);       
00798             }
00799             
00800             delete language[i];
00801             language[i] = 0;
00802             free_list.push_back(i);
00803         }
00804     }
00805 
00806     // if still empty, add new tokens
00807     if (free_list.empty()) {
00808         add_tokens();
00809     }
00810 }
00811 
00812 
00813 /* Serialization */
00814 void write_raw(ostream& os, const Sym& sym) {
00815     token_t token = sym.token();
00816     const SymVec& args = sym.args();
00817     
00818     if (is_constant(token)) {
00819         os << "c" << language[token]->c_print(vector<string>(), vector<string>()); 
00820     } else {
00821 
00822         const Var* var = dynamic_cast<const Var*>( language[token] );
00823         
00824         if (var != 0) {
00825             os << "v" << var->idx;
00826         } else {
00827             os << "f" << token << ' ' << args.size();
00828         }
00829     }
00830 
00831     for (unsigned i = 0; i < args.size(); ++i) {
00832         write_raw(os, args[i]); 
00833     }
00834 }
00835 
00836 string write_raw(const Sym& sym) {
00837     
00838     ostringstream os;
00839     write_raw(os, sym);
00840     
00841     return os.str();
00842 }
00843 
00844 Sym read_raw(istream& is) {
00845     char id = is.get();
00846 
00847     switch (id) {
00848         case 'c' : 
00849             {
00850                 double val;
00851                 is.get(); // skip '('
00852                 is >> val;
00853                 is.get(); // skip ')'
00854                 return SymConst(val);
00855             }
00856         case 'v' : 
00857             {
00858                 unsigned idx;
00859                 is >> idx;
00860                 return SymVar(idx);
00861             }
00862         case 'f' :
00863             {
00864                 token_t token;
00865                 unsigned arity;
00866                 is >> token;
00867                 is >> arity;
00868                 SymVec args(arity);
00869                 for (unsigned i = 0; i < arity; ++i) {
00870                     args[i] = read_raw(is);
00871                 }
00872 
00873                 return Sym(token, args);
00874             }
00875         default : {
00876                       cerr << "Character = " << id << " Could not read formula from stream" << endl;
00877                       exit(1);
00878                   }
00879                     
00880     }
00881 
00882     return Sym();
00883 }
00884 
00885 Sym read_raw(string str) {
00886     istringstream is(str);
00887     return read_raw(is);
00888 }
00889 
00890 void read_raw(istream& is, Sym& sym) {
00891     sym = read_raw(is);
00892 }
00893 

Generated on Thu Oct 19 05:06:40 2006 for EO by  doxygen 1.3.9.1