1
/* PeTe - Petri Engine exTremE
2
* Copyright (C) 2011 Jonas Finnemann Jensen <jopsen@gmail.com>,
3
* Thomas Søndersø Nielsen <primogens@gmail.com>,
4
* Lars Kærlund Østergaard <larsko@gmail.com>,
6
* This program is free software: you can redistribute it and/or modify
7
* it under the terms of the GNU General Public License as published by
8
* the Free Software Foundation, either version 3 of the License, or
9
* (at your option) any later version.
11
* This program is distributed in the hope that it will be useful,
12
* but WITHOUT ANY WARRANTY; without even the implied warranty of
13
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
* GNU General Public License for more details.
16
* You should have received a copy of the GNU General Public License
17
* along with this program. If not, see <http://www.gnu.org/licenses/>.
20
#include "Expressions.h"
29
namespace PetriEngine {
32
/******************** Destructors ********************/
34
BinaryExpr::~BinaryExpr(){
43
MinusExpr::~MinusExpr(){
49
LogicalCondition::~LogicalCondition(){
58
CompareCondition::~CompareCondition(){
67
NotCondition::~NotCondition(){
73
/******************** To String ********************/
75
std::string LiteralExpr::toString() const{
76
std::stringstream stream;
81
std::string IdentifierExpr::toString() const{
85
std::string BinaryExpr::toString() const{
86
return "(" + _expr1->toString() + " " + op() + " " + _expr2->toString() + ")";
89
std::string MinusExpr::toString() const{
90
return "-" + _expr->toString();
93
std::string LogicalCondition::toString() const{
94
return "(" + _cond1->toString() + " " + op() + " " + _cond2->toString() + ")";
97
std::string CompareCondition::toString() const{
98
return "(" + _expr1->toString() + " " + op() + " " + _expr2->toString() + ")";
101
std::string NotCondition::toString() const {
102
return "(not " + _cond->toString() + ")";
105
/******************** To TAPAAL Query ********************/
107
std::string LogicalCondition::toTAPAALQuery(TAPAALConditionExportContext& context) const{
108
return " ( " + _cond1->toTAPAALQuery(context) + " " + op() + " " + _cond2->toTAPAALQuery(context) + " ) ";
111
std::string CompareCondition::toTAPAALQuery(TAPAALConditionExportContext& context) const{
112
//If <id> <op> <literal>
113
if(_expr1->type() == Expr::IdentifierExpr && _expr2->type() == Expr::LiteralExpr){
114
return " ( " + context.netName + "." + _expr1->toString() + " " + opTAPAAL() + " " + _expr2->toString() + " ) ";
115
//If <literal> <op> <id>
116
}else if(_expr2->type() == Expr::IdentifierExpr && _expr1->type() == Expr::LiteralExpr){
117
return " ( " + _expr1->toString() + " " + sopTAPAAL() + " " + context.netName + "." + _expr2->toString() + " ) ";
119
context.failed = true;
124
std::string NotEqualCondition::toTAPAALQuery(TAPAALConditionExportContext& context) const{
125
return " !( " + CompareCondition::toTAPAALQuery(context) + " ) ";
128
std::string NotCondition::toTAPAALQuery(TAPAALConditionExportContext& context) const{
129
return " !( " + _cond->toTAPAALQuery(context) + " ) ";
132
/******************** opTAPAAL ********************/
134
std::string EqualCondition::opTAPAAL() const { return "="; }
135
std::string NotEqualCondition::opTAPAAL() const { return "="; } //Handled with hack in NotEqualCondition::toTAPAALQuery
136
std::string LessThanCondition::opTAPAAL() const { return "<"; }
137
std::string LessThanOrEqualCondition::opTAPAAL() const { return "<="; }
138
std::string GreaterThanCondition::opTAPAAL() const { return ">"; }
139
std::string GreaterThanOrEqualCondition::opTAPAAL() const { return ">="; }
141
std::string EqualCondition::sopTAPAAL() const { return "="; }
142
std::string NotEqualCondition::sopTAPAAL() const { return "="; } //Handled with hack in NotEqualCondition::toTAPAALQuery
143
std::string LessThanCondition::sopTAPAAL() const { return ">="; }
144
std::string LessThanOrEqualCondition::sopTAPAAL() const { return ">"; }
145
std::string GreaterThanCondition::sopTAPAAL() const { return "<="; }
146
std::string GreaterThanOrEqualCondition::sopTAPAAL() const { return "<"; }
148
/******************** Context Analysis ********************/
150
void BinaryExpr::analyze(AnalysisContext& context){
151
_expr1->analyze(context);
152
_expr2->analyze(context);
155
void MinusExpr::analyze(AnalysisContext& context){
156
_expr->analyze(context);
159
void LiteralExpr::analyze(AnalysisContext&){
163
void IdentifierExpr::analyze(AnalysisContext& context){
164
AnalysisContext::ResolutionResult result = context.resolve(_name);
166
_offsetInMarking = result.offset;
167
isPlace = result.isPlace;
170
ExprError error("Unable to resolve identifier \"" + _name + "\"",
173
context.reportError(error);
177
void LogicalCondition::analyze(AnalysisContext& context){
178
_cond1->analyze(context);
179
_cond2->analyze(context);
182
void CompareCondition::analyze(AnalysisContext& context){
183
_expr1->analyze(context);
184
_expr2->analyze(context);
187
void NotCondition::analyze(AnalysisContext &context){
188
_cond->analyze(context);
191
/******************** Evaluation ********************/
193
int BinaryExpr::evaluate(const EvaluationContext& context) const{
194
int v1 = _expr1->evaluate(context);
195
int v2 = _expr2->evaluate(context);
196
return apply(v1, v2);
199
int MinusExpr::evaluate(const EvaluationContext& context) const{
200
return -(_expr->evaluate(context));
203
int LiteralExpr::evaluate(const EvaluationContext&) const{
207
int IdentifierExpr::evaluate(const EvaluationContext& context) const{
208
assert(_offsetInMarking != -1);
210
return context.marking()[_offsetInMarking];
211
return context.assignment()[_offsetInMarking];
214
bool LogicalCondition::evaluate(const EvaluationContext& context) const{
215
bool b1 = _cond1->evaluate(context);
216
bool b2 = _cond2->evaluate(context);
220
bool CompareCondition::evaluate(const EvaluationContext& context) const{
221
int v1 = _expr1->evaluate(context);
222
int v2 = _expr2->evaluate(context);
227
bool NotCondition::evaluate(const EvaluationContext& context) const{
228
return !(_cond->evaluate(context));
231
void AssignmentExpression::evaluate(const MarkVal* m,
236
//If the same memory is used for a and result_a, do a little hack...
239
memcpy(acpy, a, sizeof(VarVal) * nvars);
240
memcpy(result_a, acpy, sizeof(VarVal) * nvars);
241
EvaluationContext context(m, acpy);
242
for(const_iter it = assignments.begin(); it != assignments.end(); it++)
243
result_a[it->offset] = it->expr->evaluate(context) % (ranges[it->offset]+1);
245
memcpy(result_a, a, sizeof(VarVal) * nvars);
246
EvaluationContext context(m, a);
247
for(const_iter it = assignments.begin(); it != assignments.end(); it++)
248
result_a[it->offset] = it->expr->evaluate(context) % (ranges[it->offset]+1);
252
/******************** Apply (BinaryExpr subclasses) ********************/
254
int PlusExpr::apply(int v1, int v2) const { return v1 + v2; }
255
int SubtractExpr::apply(int v1, int v2) const { return v1 - v2; }
256
int MultiplyExpr::apply(int v1, int v2) const { return v1 * v2; }
258
/******************** Apply (LogicalCondition subclasses) ********************/
260
bool AndCondition::apply(bool b1, bool b2) const { return b1 && b2; }
261
bool OrCondition::apply(bool b1, bool b2) const { return b1 || b2; }
263
/******************** Apply (CompareCondition subclasses) ********************/
265
bool EqualCondition::apply(int v1, int v2) const { return v1 == v2; }
266
bool NotEqualCondition::apply(int v1, int v2) const { return v1 != v2; }
267
bool LessThanCondition::apply(int v1, int v2) const { return v1 < v2; }
268
bool LessThanOrEqualCondition::apply(int v1, int v2) const { return v1 <= v2; }
269
bool GreaterThanCondition::apply(int v1, int v2) const { return v1 > v2; }
270
bool GreaterThanOrEqualCondition::apply(int v1, int v2) const { return v1 >= v2; }
272
/******************** Op (BinaryExpr subclasses) ********************/
274
std::string PlusExpr::op() const { return "+"; }
275
std::string SubtractExpr::op() const { return "-"; }
276
std::string MultiplyExpr::op() const { return "*"; }
278
/******************** Op (LogicalCondition subclasses) ********************/
280
std::string AndCondition::op() const { return "and"; }
281
std::string OrCondition::op() const { return "or"; }
283
/******************** Op (CompareCondition subclasses) ********************/
285
std::string EqualCondition::op() const { return "=="; }
286
std::string NotEqualCondition::op() const { return "!="; }
287
std::string LessThanCondition::op() const { return "<"; }
288
std::string LessThanOrEqualCondition::op() const { return "<="; }
289
std::string GreaterThanCondition::op() const { return ">"; }
290
std::string GreaterThanOrEqualCondition::op() const { return ">="; }
292
/******************** p-free Expression ********************/
294
bool BinaryExpr::pfree() const { return _expr1->pfree() && _expr2->pfree(); }
295
bool MinusExpr::pfree() const { return _expr->pfree(); }
296
bool LiteralExpr::pfree() const { return true; }
297
bool IdentifierExpr::pfree() const { return !this->isPlace; }
299
/******************** Expr::type() implementation ********************/
301
Expr::Types PlusExpr::type() const { return Expr::PlusExpr; }
302
Expr::Types SubtractExpr::type() const { return Expr::SubtractExpr; }
303
Expr::Types MultiplyExpr::type() const { return Expr::MinusExpr; }
304
Expr::Types MinusExpr::type() const { return Expr::MinusExpr; }
305
Expr::Types LiteralExpr::type() const { return Expr::LiteralExpr; }
306
Expr::Types IdentifierExpr::type() const { return Expr::IdentifierExpr; }
308
/******************** Scale Expression ********************/
310
void BinaryExpr::scale(int factor) {_expr1->scale(factor); _expr2->scale(factor);}
311
void MinusExpr::scale(int factor) {_expr->scale(factor);}
312
void LiteralExpr::scale(int factor) {_value = _value * factor;}
313
void IdentifierExpr::scale(int) {}
315
/******************** Scale Conditions ********************/
317
void LogicalCondition::scale(int factor) {_cond1->scale(factor);_cond2->scale(factor);}
318
void CompareCondition::scale(int factor) {_expr1->scale(factor);_expr2->scale(factor);}
319
void NotCondition::scale(int factor) {_cond->scale(factor);}
321
/******************** Constraint Analysis ********************/
323
void LogicalCondition::findConstraints(ConstraintAnalysisContext& context) const{
324
if(!context.canAnalyze)
326
_cond1->findConstraints(context);
327
ConstraintAnalysisContext::ConstraintSet left = context.retval;
328
_cond2->findConstraints(context);
329
mergeConstraints(context.retval, left, context.negated);
332
void AndCondition::mergeConstraints(ConstraintAnalysisContext::ConstraintSet& result,
333
ConstraintAnalysisContext::ConstraintSet& other,
336
result = Structures::StateConstraints::mergeAnd(result, other);
338
result = Structures::StateConstraints::mergeOr(result, other);
340
void OrCondition::mergeConstraints(ConstraintAnalysisContext::ConstraintSet& result,
341
ConstraintAnalysisContext::ConstraintSet& other,
344
result = Structures::StateConstraints::mergeOr(result, other);
346
result = Structures::StateConstraints::mergeAnd(result, other);
349
void CompareCondition::findConstraints(ConstraintAnalysisContext& context) const{
350
if(!context.canAnalyze)
352
context.retval.clear();
353
if(_expr1->type() == Expr::LiteralExpr && _expr2->type() == Expr::IdentifierExpr){
354
IdentifierExpr* id = (IdentifierExpr*)_expr2;
355
LiteralExpr* literal = (LiteralExpr*)_expr1;
356
addConstraints(context, literal->value(), id);
357
}else if(_expr1->type() == Expr::IdentifierExpr && _expr2->type() == Expr::LiteralExpr){
358
IdentifierExpr* id = (IdentifierExpr*)_expr1;
359
LiteralExpr* literal = (LiteralExpr*)_expr2;
360
addConstraints(context, id, literal->value());
362
context.canAnalyze = false;
365
void NotCondition::findConstraints(ConstraintAnalysisContext& context) const{
366
if(context.canAnalyze){
367
context.negated = !context.negated;
368
this->_cond->findConstraints(context);
369
context.negated = !context.negated;
373
/******************** CompareCondition::addConstraints ********************/
376
void EqualCondition::addConstraints(ConstraintAnalysisContext& context, IdentifierExpr* id, int value) const{
377
if(!context.negated){
378
Structures::StateConstraints* s = new Structures::StateConstraints(context.net());
380
s->setVarMin(id->offset(), value);
381
s->setVarMax(id->offset(), value);
383
s->setPlaceMin(id->offset(), value);
384
s->setPlaceMax(id->offset(), value);
387
context.retval.push_back(s);
389
Structures::StateConstraints* s1 = new Structures::StateConstraints(context.net());
390
Structures::StateConstraints* s2 = NULL;
392
s2 = new Structures::StateConstraints(context.net());
394
s1->setVarMin(id->offset(), value+1);
396
s2->setVarMax(id->offset(), value-1);
398
s1->setPlaceMin(id->offset(), value+1);
400
s2->setPlaceMax(id->offset(), value-1);
402
assert((s2 || value == 0) && s1);
403
context.retval.push_back(s1);
405
context.retval.push_back(s2);
409
void EqualCondition::addConstraints(ConstraintAnalysisContext& context, int value, IdentifierExpr* id) const{
410
addConstraints(context, id, value);
413
void NotEqualCondition::addConstraints(ConstraintAnalysisContext& context, IdentifierExpr* id, int value) const{
415
Structures::StateConstraints* s = new Structures::StateConstraints(context.net());
417
s->setVarMin(id->offset(), value);
418
s->setVarMax(id->offset(), value);
420
s->setPlaceMin(id->offset(), value);
421
s->setPlaceMax(id->offset(), value);
424
context.retval.push_back(s);
426
Structures::StateConstraints* s1 = new Structures::StateConstraints(context.net());
427
Structures::StateConstraints* s2 = NULL;
429
s2 = new Structures::StateConstraints(context.net());
431
s1->setVarMin(id->offset(), value+1);
433
s2->setVarMax(id->offset(), value-1);
435
s1->setPlaceMin(id->offset(), value+1);
437
s2->setPlaceMax(id->offset(), value-1);
439
assert((s2 || value == 0) && s1);
440
context.retval.push_back(s1);
442
context.retval.push_back(s2);
446
void NotEqualCondition::addConstraints(ConstraintAnalysisContext& context, int value, IdentifierExpr* id) const{
447
addConstraints(context, id, value);
450
void LessThanCondition::addConstraints(ConstraintAnalysisContext& context, IdentifierExpr* id, int value) const{
451
Structures::StateConstraints* nc = new Structures::StateConstraints(context.net());
452
if(!context.negated){
454
nc->setPlaceMax(id->offset(), value-1);
456
nc->setVarMax(id->offset(), value-1);
459
nc->setPlaceMin(id->offset(), value);
461
nc->setVarMin(id->offset(), value);
463
context.retval.push_back(nc);
466
void LessThanCondition::addConstraints(ConstraintAnalysisContext& context, int value, IdentifierExpr* id) const{
467
Structures::StateConstraints* nc = new Structures::StateConstraints(context.net());
468
if(!context.negated){
470
nc->setPlaceMin(id->offset(), value+1);
472
nc->setVarMin(id->offset(), value+1);
475
nc->setPlaceMax(id->offset(), value);
477
nc->setVarMax(id->offset(), value);
479
context.retval.push_back(nc);
483
void LessThanOrEqualCondition::addConstraints(ConstraintAnalysisContext& context, IdentifierExpr* id, int value) const{
484
Structures::StateConstraints* nc = new Structures::StateConstraints(context.net());
485
if(!context.negated){
487
nc->setPlaceMax(id->offset(), value);
489
nc->setVarMax(id->offset(), value);
492
nc->setPlaceMin(id->offset(), value+1);
494
nc->setVarMin(id->offset(), value+1);
496
context.retval.push_back(nc);
499
void LessThanOrEqualCondition::addConstraints(ConstraintAnalysisContext& context, int value, IdentifierExpr* id) const{
500
Structures::StateConstraints* nc = new Structures::StateConstraints(context.net());
501
if(!context.negated){
503
nc->setPlaceMin(id->offset(), value);
505
nc->setVarMin(id->offset(), value);
508
nc->setPlaceMax(id->offset(), value-1);
510
nc->setVarMax(id->offset(), value-1);
512
context.retval.push_back(nc);
515
void GreaterThanCondition::addConstraints(ConstraintAnalysisContext& context, IdentifierExpr* id, int value) const{
516
Structures::StateConstraints* nc = new Structures::StateConstraints(context.net());
517
if(!context.negated){
518
if(!id->pfree()) // p1 > 5
519
nc->setPlaceMin(id->offset(), value+1);
521
nc->setVarMin(id->offset(), value+1);
524
nc->setPlaceMax(id->offset(), value);
526
nc->setVarMax(id->offset(), value);
528
context.retval.push_back(nc);
531
void GreaterThanCondition::addConstraints(ConstraintAnalysisContext& context, int value, IdentifierExpr* id) const{
532
Structures::StateConstraints* nc = new Structures::StateConstraints(context.net());
533
if(!context.negated){
534
if(!id->pfree()) // 5 > p1
535
nc->setPlaceMax(id->offset(), value-1);
537
nc->setVarMax(id->offset(), value-1);
539
if(!id->pfree()) // !(5 > p1)
540
nc->setPlaceMin(id->offset(), value);
542
nc->setVarMin(id->offset(), value);
544
context.retval.push_back(nc);
547
void GreaterThanOrEqualCondition::addConstraints(ConstraintAnalysisContext& context, IdentifierExpr* id, int value) const{
548
Structures::StateConstraints* nc = new Structures::StateConstraints(context.net());
549
if(!context.negated){
550
if(!id->pfree()) // p1 >= 5
551
nc->setPlaceMin(id->offset(), value);
553
nc->setVarMin(id->offset(), value);
555
if(!id->pfree()) // !(p1 >= 5)
556
nc->setPlaceMax(id->offset(), value-1);
558
nc->setVarMax(id->offset(), value-1);
560
context.retval.push_back(nc);
563
void GreaterThanOrEqualCondition::addConstraints(ConstraintAnalysisContext& context, int value, IdentifierExpr* id) const{
564
Structures::StateConstraints* nc = new Structures::StateConstraints(context.net());
565
if(!context.negated){
566
if(!id->pfree()) // 5 >= p1
567
nc->setPlaceMax(id->offset(), value);
569
nc->setVarMax(id->offset(), value);
571
if(!id->pfree()) // !(5 >= p1)
572
nc->setPlaceMin(id->offset(), value+1);
574
nc->setVarMin(id->offset(), value+1);
576
context.retval.push_back(nc);
579
/******************** Distance Condition ********************/
581
#define MAX(v1, v2) (v1 > v2 ? v1 : v2)
582
#define MIN(v1, v2) (v1 < v2 ? v1 : v2)
584
double NotCondition::distance(DistanceContext& context) const{
586
double retval = _cond->distance(context);
591
double LogicalCondition::distance(DistanceContext& context) const{
592
double d1 = _cond1->distance(context);
593
double d2 = _cond2->distance(context);
594
return delta(d1, d2, context);
597
double AndCondition::delta(double d1,
599
const DistanceContext& context) const{
600
if(context.strategy() & DistanceContext::AndExtreme)
601
if(context.negated())
605
else if(context.strategy() & DistanceContext::AndSum)
608
return (d1 + d2) / 2;
611
double OrCondition::delta(double d1,
613
const DistanceContext& context) const{
614
if(context.strategy() & DistanceContext::OrExtreme)
615
if(context.negated())
620
return (d1 + d2) / 2;
628
int dfsArcLen(const PetriNet& net,
632
std::set<unsigned int> visited;
637
visited.insert(place);
638
while(!places.empty()){
641
for(unsigned int t = 0; t < net.numberOfTransitions(); t++){
642
if(net.outArc(t, place)){
643
for(unsigned int p = 0; p < net.numberOfPlaces(); p++){
645
if(!visited.count(p)){
652
places.push_back(sp);
662
double CompareCondition::distance(DistanceContext& context) const{
663
int v1 = _expr1->evaluate(context);
664
int v2 = _expr2->evaluate(context);
665
if(context.strategy() & DistanceContext::ArcCount){
666
int d = delta(v1, v2, context.negated());
668
if(_expr1->pfree() && !_expr2->pfree() && _expr2->type() == Expr::IdentifierExpr){
669
IdentifierExpr* id = (IdentifierExpr*)_expr2;
670
return dfsArcLen(context.net(), context.marking(), id->offset()) * d;
671
}else if(_expr2->pfree() && !_expr1->pfree() && _expr1->type() == Expr::IdentifierExpr){
672
IdentifierExpr* id = (IdentifierExpr*)_expr1;
673
return dfsArcLen(context.net(), context.marking(), id->offset()) * d;
675
} else if(context.strategy() & DistanceContext::TokenCost){
677
//TODO: Account for when we have too many tokens instead of too few
678
if(_expr1->pfree() && !_expr2->pfree() && _expr2->type() == Expr::IdentifierExpr){
679
int d = delta(v2, v1, context.negated());
681
if(d < 0) return abs(d);
682
IdentifierExpr* id = (IdentifierExpr*)_expr2;
683
return context.distanceMatrix()->tokenCost(id->offset(), d, context.marking());
684
}else if(_expr2->pfree() && !_expr1->pfree() && _expr1->type() == Expr::IdentifierExpr){
685
int d = delta(v1, v2, context.negated());
687
if(d < 0) return abs(d);
688
IdentifierExpr* id = (IdentifierExpr*)_expr1;
689
return context.distanceMatrix()->tokenCost(id->offset(), d, context.marking());
692
return abs(delta(v1, v2, context.negated()));
695
double EqualCondition::delta(int v1, int v2, bool negated) const{
699
return v1 == v2 ? 1 : 0;
702
double NotEqualCondition::delta(int v1, int v2, bool negated) const{
706
return v1 == v2 ? 1 : 0;
709
double LessThanCondition::delta(int v1, int v2, bool negated) const{
711
return v1 < v2 ? 0 : v1 - v2 + 1;
713
return v1 >= v2 ? 0 : v2 - v1;
716
double LessThanOrEqualCondition::delta(int v1, int v2, bool negated) const{
718
return v1 <= v2 ? 0 : v1 - v2;
720
return v1 > v2 ? 0 : v2 - v1 + 1;
723
double GreaterThanCondition::delta(int v1, int v2, bool negated) const{
725
return v1 > v2 ? 0 : v2 - v1 + 1;
727
return v1 <= v2 ? 0 : v1 - v2;
730
double GreaterThanOrEqualCondition::delta(int v1, int v2, bool negated) const{
732
return v1 >= v2 ? 0 : v2 - v1;
734
return v1 < v2 ? 0 : v1 - v2 + 1;
738
/******************** Just-In-Time Compilation ********************/