Statistics
| Branch: | Revision:

root / src / envir / scenario.cc @ 68da4f12

History | View | Annotate | Download (6.05 KB)

1 01873262 Georg Kunz
//==========================================================================
2
//  SCENARIO.CC - part of
3
//                     OMNeT++/OMNEST
4
//            Discrete System Simulation in C++
5
//
6
//  Author: Andras Varga
7
//
8
//==========================================================================
9
10
/*--------------------------------------------------------------*
11
  Copyright (C) 1992-2008 Andras Varga
12
  Copyright (C) 2006-2008 OpenSim Ltd.
13

14
  This file is distributed WITHOUT ANY WARRANTY. See the file
15
  `license' for details on this and other legal matters.
16
*--------------------------------------------------------------*/
17
18
#include <assert.h>
19
#include <algorithm>
20
#include <sstream>
21
#include "scenario.h"
22
#include "valueiterator.h"
23
#include "cexception.h"
24
#include "stringutil.h"
25
#include "unitconversion.h"
26
27
USING_NAMESPACE
28
29
30
/**
31
 * Resolves variables ($x, $y) and functions (sin, fabs, etc) in expressions.
32
 */
33
class Resolver : public Expression::Resolver
34
{
35
  private:
36
    Scenario *hostobject;
37
  public:
38
    Resolver(Scenario *object) {hostobject = object;}
39
    virtual ~Resolver() {};
40
    virtual Expression::Functor *resolveVariable(const char *varname);
41
    virtual Expression::Functor *resolveFunction(const char *funcname, int argcount);
42
};
43
44
Expression::Functor *Resolver::resolveVariable(const char *varname)
45
{
46
    if (varname[0]=='$')
47
        varname++;
48
    return new Scenario::VariableReference(hostobject, varname);
49
}
50
51
Expression::Functor *Resolver::resolveFunction(const char *funcname, int argcount)
52
{
53
    //FIXME check argcount!
54
    if (MathFunction::supports(funcname))
55
        return new MathFunction(funcname);
56
    else
57
        throw opp_runtime_error("Unrecognized function: %s()", funcname);
58
}
59
60
//----
61
62
Scenario::Scenario(const std::vector<IterationVariable>& iterationVariables, const char *constraintText) :
63
vars(iterationVariables)
64
{
65
    // store the constraint
66
    constraint = NULL;
67
    if (constraintText)
68
    {
69
        constraint = new Expression();
70
        Resolver resolver(this);
71
        try
72
        {
73
            constraint->parse(constraintText, &resolver);
74
        }
75
        catch (std::exception& e)
76
        {
77
            throw cRuntimeError("Cannot parse constraint expression `%s': %s", constraintText, e.what());
78
        }
79
    }
80
81
    // fill the variable tables
82
    variterators.resize(vars.size());
83
    for (int i=0; i<(int)vars.size(); i++)
84
    {
85
        ASSERT(!vars[i].varid.empty() && !vars[i].value.empty());
86
        variterators[i].parse(vars[i].value.c_str());
87
        varmap[vars[i].varid] = &variterators[i];
88
    }
89
}
90
91
Scenario::~Scenario()
92
{
93
}
94
95
Expression::Value Scenario::getIterationVariable(const char *varname)
96
{
97
    std::string value = getVariable(varname);
98
    try
99
    {
100
        if (value[0]=='"')
101
            return opp_parsequotedstr(value.c_str());  // strips quotes
102
        else if (strcmp(value.c_str(), "true")==0)
103
            return true;
104
        else if (strcmp(value.c_str(), "false")==0)
105
            return false;
106
        else
107
            return UnitConversion::parseQuantity(value.c_str()); // converts to double  FIXME units should NOT be accepted here!!!!!
108
    }
109
    catch (std::exception& e)
110
    {
111
        throw cRuntimeError("Wrong value for iteration variable %s: %s", varname, e.what());
112
    }
113
}
114
115
int Scenario::getNumRuns()
116
{
117
    if (!restart())
118
        return 0;
119
    int count = 1;
120
    while (next())
121
    {
122
        if (count>1000000)
123
            throw cRuntimeError("Are you sure you want to generate more than one million runs?");
124
        count++;
125
    }
126
    return count;
127
}
128
129
bool Scenario::restart()
130
{
131
    if (variterators.size()==0)
132
        return true;  // it is valid to have no iterations at all
133
134
    // reset all iterators. If all of them are immediately at end(), there's no
135
    // valid state and we must return false
136
    bool ok = false;
137
    for (int i=0; i<(int)variterators.size(); i++)
138
    {
139
        variterators[i].restart();
140
        if (!variterators[i].end())
141
            ok = true;
142
    }
143
    if (ok==false)
144
        return false;
145
146
    // if there's a constraint, make sure it holds
147
    while (constraint && evaluateConstraint()==false)
148
        if (!inc()) return false;
149
    return true;
150
}
151
152
bool Scenario::next()
153
{
154
    if (!inc()) return false;
155
156
    // if there's a constraint, make sure it holds
157
    while (constraint && evaluateConstraint()==false)
158
        if (!inc()) return false;
159
    return true;
160
}
161
162
bool Scenario::inc()
163
{
164
    // try incrementing the last iteration variable first
165
    for (int k=variterators.size()-1; k>=0; k--)
166
    {
167
        variterators[k]++;
168
        if (!variterators[k].end())
169
            return true; // if incrementing was OK, we're done
170
        else
171
            variterators[k].restart(); // reset this counter, and go on incrementing the (k-1)th one
172
    }
173
    return false; // no variable could be incremented
174
}
175
176
bool Scenario::evaluateConstraint()
177
{
178
    try
179
    {
180
        return constraint->boolValue();
181
    }
182
    catch (std::exception& e)
183
    {
184
        throw cRuntimeError("Cannot evaluate constraint expression: %s", e.what());
185
    }
186
}
187
188
void Scenario::gotoRun(int runNumber)
189
{
190
    // spin the iteration variables to the given run number
191
    if (!restart())
192
        throw cRuntimeError("Iterators or constraint too restrictive: not even one run can be generated");
193
    for (int i=0; i<runNumber; i++)
194
        if (!next())
195
            throw cRuntimeError("Run number %d is out of range", runNumber);
196
}
197
198
std::string Scenario::getVariable(const char *varid) const
199
{
200
    std::map<std::string,ValueIterator*>::const_iterator it = varmap.find(varid);
201
    if (it==varmap.end())
202
        throw cRuntimeError("Unknown iteration variable: %s", varid);
203
    return it->second->get();
204
}
205
206
int Scenario::getIteratorPosition(const char *varid) const
207
{
208
    std::map<std::string,ValueIterator*>::const_iterator it = varmap.find(varid);
209
    if (it==varmap.end())
210
        throw cRuntimeError("Unknown iteration variable: %s", varid);
211
    return it->second->getPosition();
212
}
213
214
std::string Scenario::str() const
215
{
216
    std::stringstream out;
217
    for (int i=0; i<(int)vars.size(); i++)
218
        out << (i>0?", ":"") << "$" << vars[i].varname << "=" << variterators[i].get();
219
    return out.str();
220
}