Line data Source code
1 : /*******************************************************************************
2 : * *
3 : * Cosmos:(C)oncept et (O)utils (S)tatistique pour les (Mo)deles *
4 : * (S)tochastiques *
5 : * *
6 : * Copyright (C) 2009-2012 LSV & LACL *
7 : * Authors: Paolo Ballarini BenoƮt Barbot & Hilal Djafri *
8 : * Website: http://www.lsv.ens-cachan.fr/Software/cosmos *
9 : * *
10 : * This program is free software; you can redistribute it and/or modify *
11 : * it under the terms of the GNU General Public License as published by *
12 : * the Free Software Foundation; either version 3 of the License, or *
13 : * (at your option) any later version. *
14 : * *
15 : * This program is distributed in the hope that it will be useful, *
16 : * but WITHOUT ANY WARRANTY; without even the implied warranty of *
17 : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
18 : * GNU General Public License for more details. *
19 : * *
20 : * You should have received a copy of the GNU General Public License along *
21 : * with this program; if not, write to the Free Software Foundation, Inc., *
22 : * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *
23 : * file expressionStruct.cpp *
24 : * Created by Benoit Barbot on 17/04/14. *
25 : *******************************************************************************
26 : */
27 :
28 :
29 : #include <cmath>
30 : #include <sstream>
31 :
32 : #include "expressionStruct.hpp"
33 :
34 : using namespace std;
35 :
36 6118 : std::ostream& text_output::operator<<(std::ostream& os, const expr& e)
37 : {
38 6118 : switch (e.t) {
39 : case Empty:
40 0 : break;
41 953 : case UnParsed: os << e.stringVal << " ";
42 953 : break;
43 0 : case ColouredPlaceHolder: os << "COLOURED ";
44 0 : break;
45 23 : case Bool: os << e.boolVal << " ";
46 23 : break;
47 1318 : case Int: os << e.intVal << " ";
48 1318 : break;
49 3395 : case Real: os << e.realVal << " ";
50 3395 : break;
51 40 : case PlaceName: os << " Marking.P->_PL_" << e.stringVal << " ";
52 40 : break;
53 60 : case ColorVarName: os << " bl.P->" << e.stringVal << ".c0 ";
54 60 : break;
55 91 : case Constant: os << e.stringVal << " ";
56 91 : break;
57 0 : case Ceil: os << " ceil(" << *(e.lhs) << ") ";
58 0 : break;
59 0 : case Floor: os << " floor(" << *(e.lhs) << ") ";
60 0 : break;
61 0 : case Exp: os << " exp(" << *(e.lhs) << ") ";
62 0 : break;
63 0 : case Plus: os << " (" << *(e.lhs) << " + " << *(e.rhs) << ") ";
64 0 : break;
65 40 : case Times: os << " (" << *(e.lhs) << " * " << *(e.rhs) << ") ";
66 40 : break;
67 0 : case Minus: os << " (" << *(e.lhs) << " - " << *(e.rhs) << ") ";
68 0 : break;
69 10 : case Div: os << " (" << *(e.lhs) << " / (double) " << *(e.rhs) << ") ";
70 10 : break;
71 0 : case Min: os << " min(" << *(e.lhs) << ", " << *(e.rhs) << ") ";
72 0 : break;
73 0 : case Max: os << " max(" << *(e.lhs) << ", " << *(e.rhs) << ") ";
74 0 : break;
75 40 : case Pow: os << " pow(" << *(e.lhs) << ", " << *(e.rhs) << ") ";
76 40 : break;
77 0 : case Neg: os << " !(" << *(e.lhs) << ") ";
78 0 : break;
79 0 : case And: os << " (" << *(e.lhs) << " && " << *(e.rhs) << ") ";
80 0 : break;
81 68 : case Or: os << " (" << *(e.lhs) << " || " << *(e.rhs) << ") ";
82 68 : break;
83 80 : case Eq: os << " (" << *(e.lhs) << " == " << *(e.rhs) << ") ";
84 80 : break;
85 0 : case Neq: os << " (" << *(e.lhs) << " != " << *(e.rhs) << ") ";
86 0 : break;
87 0 : case Leq: os << " (" << *(e.lhs) << " <= " << *(e.rhs) << ") ";
88 0 : break;
89 0 : case Sl: os << " (" << *(e.lhs) << " < " << *(e.rhs) << ") ";
90 0 : break;
91 0 : case Geq: os << " (" << *(e.lhs) << " >= " << *(e.rhs) << ") ";
92 0 : break;
93 0 : case SG: os << " (" << *(e.lhs) << " > " << *(e.rhs) << ") ";
94 0 : break;
95 0 : case In: os << " contains(" <<*(e.lhs) <<" , " << *(e.rhs) << ") ";
96 0 : break;
97 0 : case NotIn: os << " !contains((" << *(e.lhs) <<" , " << *(e.rhs) << ") ";
98 0 : break;
99 0 : case ListContinuation: os << *(e.lhs) << " , " << *(e.rhs);
100 0 : break;
101 0 : case Var: os << e.lhs->stringVal; break;
102 0 : case Lambda: os << "([] (auto "<< e.lhs->stringVal << "){" << *(e.rhs) << "})"; break;
103 0 : case App: os << "("<< e.lhs->stringVal << "(" << *(e.rhs) << "))"; break;
104 :
105 : }
106 6118 : return os;
107 : }
108 :
109 54 : bool operator< (const expr &lhs, const expr &rhs){
110 54 : if(lhs.is_concrete() && rhs.is_concrete()){
111 54 : return lhs.get_real() < rhs.get_real();
112 : }
113 0 : if( lhs.t == Bool && rhs.t == Bool)return lhs.boolVal < rhs.boolVal;
114 :
115 0 : return true;
116 : }
117 :
118 55 : bool operator== (const expr &lhs, const expr &rhs){
119 55 : return (lhs.t == rhs.t
120 55 : && (lhs.t != Bool || lhs.boolVal == rhs.boolVal)
121 55 : && (lhs.t != Int || lhs.intVal == rhs.intVal)
122 55 : && (lhs.t != Real || lhs.realVal == rhs.realVal)
123 165 : && ((lhs.t == Bool || lhs.t == Int || lhs.t == Real)
124 55 : && lhs.stringVal == rhs.stringVal
125 55 : && lhs.lhs == rhs.lhs
126 55 : && lhs.rhs == rhs.rhs)
127 55 : );
128 : }
129 55 : bool operator!= (const expr &lhs, const expr &rhs){
130 55 : return !(lhs == rhs);
131 : }
132 :
133 :
134 1519 : string expr::to_string()const {
135 : using namespace text_output;
136 3038 : stringstream ss;
137 1519 : ss << *this;
138 3038 : return ss.str();
139 : }
140 :
141 152 : std::ostream& xml_output::operator<<(std::ostream& os, const expr& e){
142 152 : switch (e.t) {
143 : case Empty:
144 0 : break;
145 0 : case UnParsed: os << "<attribute name=\"expr\"><attribute name=\"unParsed\">"<< e.stringVal << "</attribute></attribute>";
146 0 : break;
147 0 : case ColouredPlaceHolder: os << "<attribute name=\"expr\"><attribute name=\"unParsed\">COLOURED</attribute></attribute>";
148 0 : break;
149 0 : case Bool: os << "<attribute name=\"expr\"><attribute name=\"boolValue\">"<< boolalpha << e.boolVal << "</attribute></attribute>";
150 0 : break;
151 128 : case Int: os << "<attribute name=\"expr\"><attribute name=\"intValue\">"<< e.intVal << "</attribute></attribute>";
152 128 : break;
153 0 : case Real: os << "<attribute name=\"expr\"><attribute name=\"numValue\">"<< e.realVal << "</attribute></attribute>";
154 0 : break;
155 0 : case PlaceName: os << "<attribute name=\"expr\"><attribute name=\"name\">"<< e.stringVal << "</attribute></attribute>";
156 0 : break;
157 24 : case Constant: os << "<attribute name=\"expr\"><attribute name=\"name\">"<< e.stringVal << "</attribute></attribute>";
158 24 : break;
159 : case Plus:
160 0 : os << "<attribute name=\"expr\"><attribute name=\"function\"><attribute name=\"+\">" << e.lhs << e.rhs;
161 0 : os << "</attribute></attribute></attribute>";
162 0 : break;
163 : case Times:
164 0 : os << "<attribute name=\"expr\"><attribute name=\"function\"><attribute name=\"*\">" << e.lhs << e.rhs;
165 0 : os << "</attribute></attribute></attribute>";
166 0 : break;
167 : case Minus:
168 0 : os << "<attribute name=\"expr\"><attribute name=\"function\"><attribute name=\"-\">"<< e.lhs << e.rhs;
169 0 : os << "</attribute></attribute></attribute>";
170 0 : break;
171 :
172 : case Div:
173 0 : os << "<attribute name=\"expr\"><attribute name=\"function\"><attribute name=\"/\">"<< e.lhs << e.rhs;
174 0 : os << "</attribute></attribute></attribute>";
175 0 : break;
176 : default:
177 0 : cerr << "PrintXML Not yet implemented";
178 0 : exit(EXIT_FAILURE);
179 : }
180 152 : return os;
181 : }
182 :
183 372 : double expr::get_real()const{
184 372 : if(t==Int) return (double)intVal;
185 258 : else if(t==Real) return realVal;
186 0 : else return NAN;
187 :
188 : }
189 22 : expType expr::mix(const expr &le,const expr &re)const{
190 22 : const auto l=le.t;
191 22 : const auto r=re.t;
192 22 : if (l == Int && r ==Int)return Int;
193 6 : else if ((l == Real && r ==Int)|| (l == Int && r == Real)|| (l == Real && r ==Real))
194 6 : return Real;
195 0 : else if(le.is_concrete() && re.is_concrete())
196 0 : return Bool;
197 0 : else return Plus;
198 : }
199 :
200 1677 : bool expr::is_concrete()const{
201 1677 : return (t== Int || t == Real || t==boolVal);
202 : }
203 :
204 96 : bool expr::empty()const{
205 96 : return (t==Empty || (t==UnParsed && stringVal.empty()));
206 : }
207 :
208 0 : bool expr::is_zero()const{
209 0 : return empty() || (t== Int && intVal == 0) || ( t == Real && realVal == 0.0);
210 : }
211 :
212 100 : void expr::rewrite( function<void(expr&)> f){
213 100 : switch (t) {
214 : case Constant:
215 : case Empty:
216 : case UnParsed:
217 : case PlaceName:
218 : case Bool:
219 : case Int:
220 : case Real:
221 : case Var:
222 : case Lambda:
223 : case ColouredPlaceHolder:
224 : case ColorVarName:
225 : // 0-ary
226 63 : f(*this);
227 63 : break;
228 :
229 : case App:
230 : //unary right
231 0 : rhs->rewrite(f);
232 0 : f(*this);
233 0 : break;
234 :
235 : case Ceil:
236 : case Floor:
237 : case Neg:
238 : case Exp:
239 : //unary left
240 0 : lhs->rewrite(f);
241 0 : f(*this);
242 0 : break;
243 :
244 : case In:
245 : case NotIn:
246 : case Plus:
247 : case Times:
248 : case Minus:
249 : case Div:
250 : case Min:
251 : case Max:
252 : case Pow:
253 : case And:
254 : case Or:
255 : case Eq:
256 : case Neq:
257 : case Leq:
258 : case Sl:
259 : case Geq:
260 : case SG:
261 : case ListContinuation:
262 : //binary
263 37 : lhs->rewrite(f);
264 37 : rhs->rewrite(f);
265 37 : f(*this);
266 37 : break;
267 : }
268 100 : }
269 :
270 :
271 469 : void expr::eval(const map<string,int> &intconst,const map<string,double> &realconst){
272 469 : switch (t) {
273 : case Constant:
274 : {
275 11 : const auto it = intconst.find(stringVal);
276 11 : if(it != intconst.end()){
277 11 : t=Int;
278 11 : intVal = it->second;
279 : }else{
280 0 : const auto it = realconst.find(stringVal);
281 0 : if(it != realconst.end()){
282 0 : t=Real;
283 0 : realVal = it->second;
284 : }
285 : }
286 : }
287 11 : break;
288 : case Empty:
289 : case UnParsed:
290 : case PlaceName:
291 : case Bool:
292 : case Int:
293 : case Real:
294 : case Var:
295 : case Lambda:
296 : case ColouredPlaceHolder:
297 : case In:
298 : case NotIn:
299 : case ColorVarName:
300 436 : break;
301 : case App:
302 0 : rhs->eval(intconst,realconst);
303 0 : break;
304 : case ListContinuation:
305 0 : lhs->eval(intconst,realconst);
306 0 : rhs->eval(intconst,realconst);
307 0 : break;
308 : case Ceil:
309 : case Floor:
310 : case Neg:
311 : case Exp:
312 0 : lhs->eval(intconst,realconst);
313 0 : if (lhs->t==Int){
314 0 : expr tmp = *lhs;
315 0 : *this= tmp;
316 0 : } else if(lhs->t==Real){
317 0 : if(t==Floor)intVal = (int)floor(lhs->realVal);
318 0 : else intVal=(int)ceil(lhs->realVal);
319 0 : t= Int;
320 0 : lhs.reset();
321 0 : } else if(lhs->t==Bool){
322 0 : t=Bool;
323 0 : boolVal = !lhs->boolVal;
324 0 : lhs.reset();
325 : }
326 0 : break;
327 : case Plus:
328 : case Times:
329 : case Minus:
330 : case Div:
331 : case Min:
332 : case Max:
333 : case Pow:
334 : case And:
335 : case Or:
336 : case Eq:
337 : case Neq:
338 : case Leq:
339 : case Sl:
340 : case Geq:
341 : case SG:
342 22 : lhs->eval(intconst,realconst);
343 22 : rhs->eval(intconst,realconst);
344 22 : expType t2=mix(*rhs,*lhs);
345 22 : if(t2==Int) {
346 16 : switch (t) {
347 16 : case Plus: intVal = lhs->intVal + rhs->intVal;
348 16 : break;
349 0 : case Times: intVal = lhs->intVal * rhs->intVal;
350 0 : break;
351 0 : case Minus: intVal = lhs->intVal - rhs->intVal;
352 0 : break;
353 0 : case Div: intVal = lhs->intVal / rhs->intVal;
354 0 : break;
355 0 : case Min: intVal = min(lhs->intVal,rhs->intVal);
356 0 : break;
357 0 : case Max: intVal = max(lhs->intVal,rhs->intVal);
358 0 : break;
359 0 : case Pow: intVal = (lhs->intVal)^(rhs->intVal);
360 0 : break;
361 : default:
362 0 : break;
363 : }
364 16 : t = Int;
365 16 : lhs.reset();
366 16 : rhs.reset();
367 6 : } else if (t2==Real ){
368 6 : switch (t) {
369 0 : case Plus: realVal = lhs->get_real() + rhs->get_real();
370 0 : break;
371 6 : case Times: realVal = lhs->get_real() * rhs->get_real();
372 6 : break;
373 0 : case Minus: realVal = lhs->get_real() - rhs->get_real();
374 0 : break;
375 0 : case Div: realVal = lhs->get_real() / rhs->get_real();
376 0 : break;
377 0 : case Min: realVal = min(lhs->get_real(),rhs->get_real());
378 0 : break;
379 0 : case Max: realVal = max(lhs->get_real(),rhs->get_real());
380 0 : break;
381 0 : case Pow: realVal = pow(lhs->get_real(),rhs->get_real());
382 0 : break;
383 : default:
384 0 : break;
385 : }
386 6 : t = Real;
387 6 : lhs.reset();
388 6 : rhs.reset();
389 0 : } else if (t2 == Bool){
390 0 : switch (t) {
391 0 : case And: boolVal = lhs->boolVal && rhs->boolVal;
392 0 : break;
393 0 : case Or: boolVal = lhs->boolVal || rhs->boolVal;
394 0 : break;
395 0 : case Eq: boolVal = lhs->get_real() == rhs->get_real();
396 0 : break;
397 0 : case Leq: boolVal = lhs->get_real() <= rhs->get_real();
398 0 : break;
399 0 : case Sl: boolVal = lhs->get_real() < rhs->get_real();
400 0 : break;
401 0 : case Geq: boolVal = lhs->get_real() >= rhs->get_real();
402 0 : break;
403 0 : case SG: boolVal = lhs->get_real() > rhs->get_real();
404 0 : break;
405 : default:
406 0 : break;
407 : }
408 0 : t = Bool;
409 0 : lhs.reset();
410 0 : rhs.reset();
411 : }
412 22 : break;
413 : }
414 469 : }
415 :
416 :
417 :
418 64 : void expr::eval(){
419 64 : eval(map<string,int>(), map<string,double>());
420 64 : }
421 :
422 5711 : void expr::get_places(set<string> & acset)const{
423 5711 : if(t==PlaceName)acset.insert(stringVal);
424 5711 : if(lhs.use_count()>0)lhs->get_places(acset);
425 5711 : if(rhs.use_count()>0)rhs->get_places(acset);
426 5711 : }
427 :
428 3243 : bool expr::is_markDep()const{
429 6486 : set<string> accset;
430 3243 : get_places(accset);
431 6486 : return !accset.empty();
432 105 : }
|