NumeRe v1.1.4
NumeRe: Framework für Numerische Rechnungen
interval.cpp
Go to the documentation of this file.
1/*****************************************************************************
2 NumeRe: Framework fuer Numerische Rechnungen
3 Copyright (C) 2021 Erik Haenel et al.
4
5 This program is free software: you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation, either version 3 of the License, or
8 (at your option) any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17******************************************************************************/
18
19
20#include "interval.hpp"
21#include "../kernel.hpp"
22#include "utils/tools.hpp"
23
24// Prototype from parser_functions.hpp
25size_t findVariableInExpression(const std::string& sExpr, const std::string& sVarName, size_t nPosStart);
26
27
36void Interval::assign(const Interval& ivl)
37{
38 name = ivl.name;
41}
42
43
53double Interval::getSample(size_t n, size_t nSamples) const
54{
55 // Too few samples are not reasonable
56 if (nSamples < 2)
58
59 // Depending on the number of elements in the internal
60 // interval, we'll interpret the interval access different
61 if (m_vInterval.size() == 2)
62 // Usual interval access using the two values as start
63 // and end of the interval
64 return m_vInterval.front() + (m_vInterval.back() - m_vInterval.front()) / (double)(nSamples-1) * n;
65 else if (m_vInterval.size() == nSamples)
66 {
67 // In this case we have more than two values in
68 // the internal array and the selected number of
69 // samples corresponds to the array length - we
70 // simply return the corresponding array entries
71 if (m_vInterval.size() > n)
72 return m_vInterval[n];
73 else
74 return m_vInterval.back();
75 }
76 else
77 {
78 // In this case we have more than two values in
79 // the internal array but the selected number of
80 // samples is different from the array length.
81 // We use linear interpolation between the array
82 // values to handle this
83 double val = (m_vInterval.size()-1) / (double)(nSamples-1) * n;
84 size_t nIdx = (size_t)val;
85 val -= nIdx;
86
87 if (nIdx < m_vInterval.size()+1)
88 return m_vInterval[nIdx] + val * (m_vInterval[nIdx+1] - m_vInterval[nIdx]);
89 else if (nIdx < m_vInterval.size())
90 return m_vInterval[nIdx] + val * (m_vInterval[nIdx] - m_vInterval[nIdx-1]);
91 else
92 return m_vInterval.back() + (val + nIdx - m_vInterval.size() + 1) * (m_vInterval.back() - m_vInterval[m_vInterval.size()-2]);
93 }
94}
95
96
106Interval::Interval(const std::string& sDef) : Interval()
107{
108 reset(sDef);
109}
110
111
121{
122 reset(dFront, dBack);
123}
124
125
133{
134 assign(ivl);
135}
136
137
146{
147 assign(ivl);
148 return *this;
149}
150
151
160mu::value_type Interval::operator()(size_t n, size_t nSamples) const
161{
162 return getSample(n, nSamples);
163}
164
165
174mu::value_type Interval::log(size_t n, size_t nSamples) const
175{
176 return std::pow(10.0, std::log10(front()) + (double)n * (std::log10(back()) - std::log10(front())) / (double)(nSamples - 1));
177}
178
179
188{
189 return m_vInterval.front();
190}
191
192
201{
202 return m_vInterval.back();
203}
204
205
214{
215 return *std::min_element(m_vInterval.begin(), m_vInterval.end());
216}
217
218
227{
228 return *std::max_element(m_vInterval.begin(), m_vInterval.end());
229}
230
231
239double Interval::min() const
240{
241 return *std::min_element(m_vInterval.begin(), m_vInterval.end());
242}
243
244
252double Interval::max() const
253{
254 return *std::max_element(m_vInterval.begin(), m_vInterval.end());
255}
256
257
265double Interval::range() const
266{
267 return max() - min();
268}
269
270
278double Interval::middle() const
279{
280 return 0.5 * (max() + min());
281}
282
283
293{
294 return (m_vInterval.size() == 2 && val.real() >= min() && val.real() <= max())
295 || std::find(m_vInterval.begin(), m_vInterval.end(), val.real()) != m_vInterval.end();
296}
297
298
308bool Interval::contains(const std::string& sVarName) const
309{
310 return findVariableInExpression(m_sDefinition, sVarName) != std::string::npos;
311}
312
313
323{
324 if (m_vInterval.size() == 2)
325 return 0u;
326
327 return m_vInterval.size();
328}
329
330
340{
341 if (!m_sDefinition.length())
342 return;
343
344 auto indices = getAllIndices(m_sDefinition);
347
348 // Examine the number of indices. If only one value then it
349 // might be a singleton or a data object as interval
350 if (indices.size() == 1)
351 {
352 // Get the data elements
353 if (_data.containsTablesOrClusters(indices.front()))
354 getDataElements(indices.front(), _parser, _data, NumeReKernel::getInstance()->getSettings());
355
356 // Parse the index
357 _parser.SetExpr(indices.front());
359 int nResults;
360
361 // Get the return values
362 v = _parser.Eval(nResults);
363
364 // Assign the values depending on their
365 // number
366 if (nResults == 1)
367 m_vInterval.assign(2, v[0].real());
368 else
369 {
370 m_vInterval.clear();
371
372 for (int i = 0; i < nResults; i++)
373 m_vInterval.push_back(v[i].real());
374 }
375 }
376 else
377 {
378 m_vInterval.clear();
379
380 // Parse every index
381 for (size_t i = 0; i < indices.size(); i++)
382 {
383 // Get possible data elements
384 if (_data.containsTablesOrClusters(indices[i]))
385 getDataElements(indices[i], _parser, _data, NumeReKernel::getInstance()->getSettings());
386
387 _parser.SetExpr(indices[i]);
388 m_vInterval.push_back(_parser.Eval().real());
389 }
390 }
391}
392
393
402void Interval::reset(const std::string& sDef)
403{
404 m_sDefinition = sDef;
405 refresh();
406}
407
408
418{
419 m_vInterval.assign({dFront.real(), dBack.real()});
420}
421
422
434void Interval::expand(double perc, double dMin)
435{
436 double r = range();
437 double mi = min();
438 double ma = max();
439
440 if (r == 0.0 || r < 1e-4 * mi)
441 r = fabs(ma);
442
443 double mi2 = mi - r * (perc - 1.0) * 0.5;
444 ma += r * (perc - 1.0) * 0.5;
445
446 if (mi2 <= dMin)
447 {
448 if (mi > dMin)
449 mi2 = mi;
450 else
451 mi = dMin + r * (perc - 1.0) * 0.5;
452 }
453
454 reset(mi2, ma);
455}
456
457
467{
468 if (isnan(m_vInterval.front()))
469 return _ivl;
470 else if (isnan(_ivl.m_vInterval.front()))
471 return *this;
472
473 return Interval(std::min(this->min(), _ivl.min()), std::max(this->max(), _ivl.max()));
474}
475
476
477
478
479
489IntervalSet::IntervalSet(const std::string& sIntervalString)
490{
491 if (findParameter(sIntervalString, "x", '='))
492 {
493 intervals.push_back(Interval(getArgAtPos(sIntervalString, findParameter(sIntervalString, "x", '=') + 1)));
494 intervals.back().name = "x";
495 }
496
497 if (findParameter(sIntervalString, "y", '='))
498 {
499 intervals.push_back(Interval(getArgAtPos(sIntervalString, findParameter(sIntervalString, "y", '=') + 1)));
500 intervals.back().name = "y";
501 }
502
503 if (findParameter(sIntervalString, "z", '='))
504 {
505 intervals.push_back(Interval(getArgAtPos(sIntervalString, findParameter(sIntervalString, "z", '=') + 1)));
506 intervals.back().name = "z";
507 }
508
509 if (findParameter(sIntervalString, "t", '='))
510 {
511 intervals.push_back(Interval(getArgAtPos(sIntervalString, findParameter(sIntervalString, "t", '=') + 1)));
512 intervals.back().name = "t";
513 }
514
515 // Read the interval syntax
516 if (sIntervalString.find('[') != std::string::npos && getMatchingParenthesis(sIntervalString.substr(sIntervalString.find('['))) != std::string::npos)
517 {
518 size_t nPos = 0;
519 size_t nMatchingParens = 0;
520 size_t nPrevChar = 0;
521
522 // Find the correct interval bracket
523 do
524 {
525 nPos = sIntervalString.find('[', nPos);
526
527 if (nPos == std::string::npos || (nMatchingParens = getMatchingParenthesis(sIntervalString.substr(nPos))) == std::string::npos)
528 break;
529
530 nMatchingParens += nPos;
531 nPrevChar = sIntervalString.find_last_not_of(" [", nPos);
532 nPos++;
533 }
534 while (isInQuotes(sIntervalString, nPos) || (nPrevChar != std::string::npos && sIntervalString[nPrevChar] == '='));
535
536 // If an interval bracket was found
537 if (nPos != std::string::npos && nMatchingParens != std::string::npos)
538 {
539 std::string sRanges = sIntervalString.substr(nPos, nMatchingParens - nPos);
540
541 // Split the whole argument list
542 auto args = getAllArguments(sRanges);
543 static std::string sNames[4] = {"x", "y", "z", "t"};
544
545 for (size_t i = 0; i < args.size(); i++)
546 {
547 intervals.push_back(Interval(args[i]));
548
549 if (i < 4)
550 intervals.back().name = sNames[i];
551 }
552 }
553 }
554}
555
556
564{
565 intervals = ivSet.intervals;
566}
567
568
577{
578 intervals = ivSet.intervals;
579 return *this;
580}
581
582
591{
592 if (n < intervals.size())
593 return intervals[n];
594
595 return intervals.back();
596}
597
598
606const Interval& IntervalSet::operator[](size_t n) const
607{
608 if (n < intervals.size())
609 return intervals[n];
610
611 return intervals.back();
612}
613
614
623{
624 for (size_t i = 0; i < intervals.size(); i++)
625 {
626 for (size_t j = 0; j < intervals.size(); j++)
627 {
628 if (i != j && intervals[j].contains(intervals[i].name))
629 return true;
630 }
631 }
632
633 return false;
634}
635
636
643size_t IntervalSet::size() const
644{
645 return intervals.size();
646}
647
648
656std::vector<mu::value_type> IntervalSet::convert()
657{
658 std::vector<mu::value_type> vIntervals;
659
660 for (const Interval& ivl : intervals)
661 {
662 vIntervals.push_back(ivl.front());
663 vIntervals.push_back(ivl.back());
664 }
665
666 return vIntervals;
667}
668
669
677void IntervalSet::setNames(const std::vector<std::string>& vNames)
678{
679 for (size_t i = 0; i < vNames.size(); i++)
680 {
681 if (intervals.size() <= i)
682 break;
683
684 intervals[i].name = vNames[i];
685 }
686}
687
688
This class represents a single interval in code providing reading access functionality.
Definition: interval.hpp:34
void expand(double perc, double dMin=-INFINITY)
Expand the interval by the corresponding percentage. The expansion is equally distributed to both end...
Definition: interval.cpp:434
void assign(const Interval &ivl)
Assign a interval object to this instance.
Definition: interval.cpp:36
Interval combine(const Interval &_ivl) const
Returns the (continous) interval, which contains this and the passed interval.
Definition: interval.cpp:466
mu::value_type back() const
Return the last element in the interval.
Definition: interval.cpp:200
void refresh()
Referesh the internal interval representation (e.g. after a dependency has been updated).
Definition: interval.cpp:339
std::string m_sDefinition
Definition: interval.hpp:36
size_t getSamples() const
Returns the number of internal samples. Will return zero, if the internal samples are only interval s...
Definition: interval.cpp:322
double getSample(size_t n, size_t nSamples) const
Return the nth sample of the interval using the desired number of samples.
Definition: interval.cpp:53
double range() const
Return the real inteval range of this interval.
Definition: interval.cpp:265
void reset(const std::string &sDef)
Reset the interval with a new definition.
Definition: interval.cpp:402
mu::value_type cmax() const
Return the componentwise maximal element in the interval.
Definition: interval.cpp:226
double middle() const
Calculates the middle point of the interval.
Definition: interval.cpp:278
std::string name
Definition: interval.hpp:43
bool isInside(mu::value_type val) const
Checks, whether the passed value is part of this interval.
Definition: interval.cpp:292
mu::value_type front() const
Return the first element in the interval.
Definition: interval.cpp:187
std::vector< double > m_vInterval
Definition: interval.hpp:37
Interval & operator=(const Interval &ivl)
Assignment operator overload.
Definition: interval.cpp:145
double max() const
Return the maximal element in the interval.
Definition: interval.cpp:252
Interval()
Definition: interval.hpp:45
bool contains(const std::string &sVarName) const
Check, whether a variable is part of the interval definition string to detect a possible dependency.
Definition: interval.cpp:308
mu::value_type log(size_t n, size_t nSamples=100) const
Return a sample in logarithmic scale.
Definition: interval.cpp:174
mu::value_type operator()(size_t n, size_t nSamples=100) const
Parenthesis operator overload.
Definition: interval.cpp:160
mu::value_type cmin() const
Return the componentwise minimal element in the interval.
Definition: interval.cpp:213
double min() const
Return the minimal element in the interval.
Definition: interval.cpp:239
This class represents the central memory managing instance. It will handle all tables and clusters,...
bool containsTablesOrClusters(const std::string &sCmdLine)
This member function evaluates, whether the passed command line contains tables or clusters.
static NumeReKernel * getInstance()
This static member function returns a a pointer to the singleton instance of the kernel.
Definition: kernel.hpp:221
mu::Parser & getParser()
Definition: kernel.hpp:281
MemoryManager & getMemoryManager()
Definition: kernel.hpp:263
Settings & getSettings()
Definition: kernel.hpp:296
Common exception class for all exceptions thrown in NumeRe.
Definition: error.hpp:32
@ INVALID_INDEX
Definition: error.hpp:129
static size_t invalid_position
Definition: error.hpp:235
void SetExpr(StringView a_sExpr)
Set the expression. Triggers first time calculation thus the creation of the bytecode and scanning of...
value_type Eval()
Single-value wrapper around the vectorized overload of this member function.
Mathematical expressions parser.
Definition: muParser.h:51
string getDataElements(string &sLine, Parser &_parser, MemoryManager &_data, const Settings &_option, int options)
Searches the passed string for calls to any table or cluster and replaces them with internal vectors ...
Definition: dataaccess.cpp:276
size_t findVariableInExpression(const std::string &sExpr, const std::string &sVarName, size_t nPosStart)
This function searches for the selected variable in the passed string and returns the position of the...
unsigned int getMatchingParenthesis(const StringView &)
Returns the position of the closing parenthesis.
Definition: tools.cpp:414
MUP_BASETYPE value_type
The numeric datatype used by the parser.
Definition: muParserDef.h:251
bool isnan(const value_type &v)
Definition: muParserDef.h:379
std::vector< double > real(const std::vector< value_type > &vVec)
char name[32]
Definition: resampler.cpp:371
#define min(a, b)
Definition: resampler.cpp:34
#define max(a, b)
Definition: resampler.cpp:30
int findParameter(const std::string &sCmd, const std::string &sParam, const char cFollowing)
This function searches the passed parameter in the passed command string. If something is found,...
Definition: tools.cpp:113
This class represents a set of intervals used together for calculations and simulations.
Definition: interval.hpp:84
std::vector< mu::value_type > convert()
Convert the new interval data types to the old plain mu::value_type values.
Definition: interval.cpp:656
size_t size() const
Return the number of intervals.
Definition: interval.cpp:643
void setNames(const std::vector< std::string > &vNames)
Set the interval names.
Definition: interval.cpp:677
IntervalSet()=default
bool hasDependentIntervals() const
Detect, whether there are intervals, which depend on each other.
Definition: interval.cpp:622
std::vector< Interval > intervals
Definition: interval.hpp:85
Interval & operator[](size_t n)
Access operator overload.
Definition: interval.cpp:590
IntervalSet & operator=(const IntervalSet &ivSet)
Assignment operator overload.
Definition: interval.cpp:576
string getArgAtPos(const string &sCmd, unsigned int nPos, int extraction)
Extracts a options value at the selected position and applies automatic parsing, if necessary.
Definition: tools.cpp:1598
bool isInQuotes(StringView sExpr, unsigned int nPos, bool bIgnoreVarParser)
Checks, whether the position in the passed expression is part of a string literal.
Definition: tools.cpp:1672
EndlessVector< string > getAllIndices(string sArgList)
Splits up the complete index list and returns them as an EndlessVector.
Definition: tools.cpp:2384
EndlessVector< StringView > getAllArguments(StringView sArgList)
Splits up the complete argument list and returns them as an EndlessVector.
Definition: tools.cpp:2346