// This file is part of fityk program. Copyright (C) Marcin Wojdyr
// Licence: GNU General Public License version 2
// $Id: settings.cpp 322 2007-07-24 00:17:11Z wojdyr $
#include "common.h"
#include "settings.h"
#include "logic.h"
#include "fit.h"
#include <ctype.h>
#include <algorithm>
#include <stdlib.h>
#include <ctime> //time()
using namespace std;
fp epsilon = 1e-12; // declared in common.h
/// small utility used only in constructor
void Settings::insert_enum(string const& name,
map<char,string> const& e, char value)
{
epar.insert(pair<string, EnumString> (name, EnumString(e, value)));
}
Settings::Settings(Ftk const* F_)
: F(F_)
{
// general
map<char, string> verbosity_enum;
verbosity_enum [-1]= "quiet";
verbosity_enum [0] = "normal";
verbosity_enum [1] = "verbose";
verbosity_enum [2] = "debug";
insert_enum("verbosity", verbosity_enum, 0);
map<char, string> autoplot_enum;
autoplot_enum [1] = "never";
autoplot_enum [2] = "on-plot-change";
autoplot_enum [3] = "on-fit-iteration";
insert_enum("autoplot", autoplot_enum, 2);
bpar["exit-on-warning"] = false;
fpar["epsilon"] = epsilon;
map<char, string> data_sigma_enum;
data_sigma_enum ['s'] = "sqrt";
data_sigma_enum ['1'] = "one";
insert_enum("data-default-sigma", data_sigma_enum, 's');
// 0 -> time-based seed
ipar["pseudo-random-seed"] = 0;
map<char, string> sum_export_style_enum;
sum_export_style_enum [0] = "normal";
sum_export_style_enum [1] = "gnuplot";
insert_enum("formula-export-style", sum_export_style_enum, 0);
// Function
fpar["cut-function-level"] = cut_function_level = 0.;
// guess
bpar ["can-cancel-guess"] = true;
fpar ["height-correction"] = 1.;
fpar ["width-correction"] = 1.;
fpar ["guess-at-center-pm"] = 1.;
//Fit
map<char, string> fitting_method_enum;
vector<Fit*> const& fm = F->get_fit_container()->get_methods();
for (int i = 0; i < size(fm); ++i)
fitting_method_enum[i] = fm[i]->name;
insert_enum("fitting-method", fitting_method_enum, 0);
// - common
ipar["max-wssr-evaluations"] = 1000;
fpar["variable-domain-percent"] = 30.;
// - Lev-Mar
fpar["lm-lambda-start"] = 0.001;
fpar["lm-lambda-up-factor"] = 10;
fpar["lm-lambda-down-factor"] = 10;
fpar["lm-stop-rel-change"] = 1e-4;
fpar["lm-max-lambda"] = 1e+15;
// - Nelder-Mead
fpar["nm-convergence"] = 0.0001;
bpar["nm-move-all"] = false;
map<char, string> distrib_enum;
distrib_enum ['u'] = "uniform";
distrib_enum ['g'] = "gauss";
distrib_enum ['l'] = "lorentz";
distrib_enum ['b'] = "bound";
insert_enum("nm-distribution", distrib_enum, 'b');
fpar["nm-move-factor"] = 1;
// - Genetic Algorithms
//TODO
}
string Settings::getp(string const& k) const
{
if (ipar.count(k)) {
return S(ipar.find(k)->second);
}
else if (fpar.count(k)) {
return S(fpar.find(k)->second);
}
else if (bpar.count(k)) {
return bpar.find(k)->second ? "1" : "0";
}
else if (irpar.count(k)) {
return S(irpar.find(k)->second.v);
}
else if (epar.count(k)) {
EnumString const& ens = epar.find(k)->second;
return ens.e.find(ens.v)->second;
}
else if (spar.count(k)) {
return "\"" + spar.find(k)->second + "\"";
}
else
throw ExecuteError("Unknown option: " + k);
}
void Settings::setp_core(string const& k, string const& v)
{
if (ipar.count (k)) {
int d;
if (istringstream (v) >> d) {
ipar[k] = d;
if (k == "pseudo-random-seed")
do_srand();
return;
}
}
else if (fpar.count (k)){
fp d;
if (istringstream (v) >> d) {
fpar[k] = d;
//optimization
if (k == "cut-function-level")
cut_function_level = d;
else if (k == "epsilon") {
if (d <= 0.) {
throw ExecuteError("Value of epsilon must be positive.");
}
epsilon = d;
}
return;
}
}
else if (bpar.count (k)){
bool d;
if (istringstream (v) >> d) {
bpar[k] = d;
return;
}
}
else if (irpar.count (k)) {
int d = -1;
istringstream (v) >> d;
if (irpar[k].l <= d && d <= irpar[k].u) {
irpar[k].v = d;
return;
}
}
else if (epar.count (k)){
EnumString& t = epar.find(k)->second;
for (map<char,string>::const_iterator i = t.e.begin();
i != t.e.end(); i++)
if (i->second == v) {
t.v = i->first;
return;
}
}
else if (spar.count (k)){
spar[k] = v;
return;
}
throw ExecuteError("'" + v + "' is not a valid value for '" + k + "'");
}
string Settings::infop (string const& k)
{
return k + " = " + getp(k) + "\ntype: " + typep(k);
}
void Settings::setp (string const& k, string const& v)
{
string sp = getp(k);
if (sp == v)
F->msg("Option '" + k + "' already has value: " + v);
else {
setp_core (k, v);
F->msg("Value for '" + k + "' changed from '" + sp + "' to '" + v+"'");
}
}
string Settings::typep (string const& k) const
{
if (ipar.count (k)){
return "integer number";
}
else if (fpar.count (k)){
return "real number";
}
else if (bpar.count (k)){
return "boolean (0/1)";
}
else if (irpar.count (k)){
int u = irpar.find(k)->second.u;
int l = irpar.find(k)->second.l;
assert(u - l >= 1);
return "integer from range: " + S(l) + ", ..., " + S(u);
}
else if (epar.count (k)){
map<char,string> const& e = epar.find(k)->second.e;
return "one of: " + join_vector(get_map_values(e), ", ");
}
else if (spar.count (k)){
return "string (a-zA-Z0-9+-.)";
}
else
throw ExecuteError("Unknown option: " + k);
}
vector<string> Settings::expanp(string const& k) const
{
vector<string> e;
int len = k.size();
for (map<string,int>::const_iterator i = ipar.begin(); i!=ipar.end();i++)
if (!string(i->first, 0, len).compare (k))
e.push_back (i->first);
for (map<string,fp>::const_iterator i = fpar.begin(); i!=fpar.end(); i++)
if (!string(i->first, 0, len).compare (k))
e.push_back (i->first);
for (map<string,bool>::const_iterator i = bpar.begin();i!=bpar.end();i++)
if (!string(i->first, 0, len).compare (k))
e.push_back (i->first);
for (map<string, IntRange>::const_iterator i = irpar.begin();
i != irpar.end(); i++)
if (!string(i->first, 0, len).compare (k))
e.push_back (i->first);
for (map<string, EnumString>::const_iterator i = epar.begin();
i != epar.end(); i++)
if (!string(i->first, 0, len).compare (k))
e.push_back (i->first);
for (map<string, string>::const_iterator i = spar.begin();
i != spar.end(); i++)
if (!string(i->first, 0, len).compare (k))
e.push_back (i->first);
sort(e.begin(), e.end());
return e;
}
vector<string> Settings::expand_enum(string const& k, string const& t) const
{
vector<string> r;
if (epar.count(k) == 0)
throw ExecuteError("Unknown option: " + k);
map<char, string> const& es = epar.find(k)->second.e;
for (map<char,string>::const_iterator i = es.begin(); i != es.end(); i++)
if (!string(i->second, 0, t.size()).compare(t))
r.push_back (i->second);
return r;
}
string Settings::print_usage() const
{
string s = "Usage: \n\tset option = value\n"
"or, to see the current value: \n\t"
"set option\n"
"Available options:";
vector<string> e = expanp();
for (vector<string>::const_iterator i = e.begin(); i != e.end(); i++){
s += "\n " + *i + " = <" + typep(*i) + ">, current value: "+getp(*i);
}
return s;
}
/// it doesn't set autoplot and verbosity options
string Settings::set_script() const
{
vector<string> e = expanp();
string s;
for (vector<string>::const_iterator i = e.begin(); i != e.end(); i++) {
if (*i == "autoplot" || *i == "verbosity")
continue;
string v = getp(*i);
s += "set " + *i + " = " + (v.empty() ? "\"\"" : v) + "\n";
}
return s;
}
void Settings::do_srand()
{
int random_seed = get_i("pseudo-random-seed");
int rs = random_seed >= 0 ? random_seed : time(0);
srand(rs);
F->vmsg("Seed for a sequence of pseudo-random numbers: " + S(rs));
}
void Settings::set_temporary(std::string const& k, std::string const& v)
{
old_values.push_back(make_pair(k, getp(k)));
setp_core(k, v);
}
void Settings::clear_temporary()
{
while(!old_values.empty()) {
setp_core(old_values.back().first, old_values.back().second);
old_values.pop_back();
}
}
syntax highlighted by Code2HTML, v. 0.9.1