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>,
5
* Peter Gjøl Jensen <root@petergjoel.dk>
7
* This program is free software: you can redistribute it and/or modify
8
* it under the terms of the GNU General Public License as published by
9
* the Free Software Foundation, either version 3 of the License, or
10
* (at your option) any later version.
12
* This program is distributed in the hope that it will be useful,
13
* but WITHOUT ANY WARRANTY; without even the implied warranty of
14
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
* GNU General Public License for more details.
17
* You should have received a copy of the GNU General Public License
18
* along with this program. If not, see <http://www.gnu.org/licenses/>.
20
#include "PetriEngine/PQL/Contexts.h"
21
#include "PetriEngine/PQL/Expressions.h"
22
#include "PetriEngine/errorcodes.h"
23
#include "PetriEngine/PQL/Visitor.h"
34
using namespace PetriEngine::Simplification;
36
namespace PetriEngine {
39
std::ostream& generateTabs(std::ostream& out, uint32_t tabs) {
41
for(uint32_t i = 0; i < tabs; i++) {
47
/** FOR COMPILING AND CONSTRUCTING LOGICAL OPERATORS **/
50
void tryMerge(std::vector<Condition_ptr>& _conds, const Condition_ptr& ptr, bool aggressive = false)
52
if(auto lor = std::dynamic_pointer_cast<T>(ptr))
54
for(auto& c : *lor) tryMerge<T>(_conds, c, aggressive);
58
_conds.emplace_back(ptr);
60
else if (auto comp = std::dynamic_pointer_cast<CompareCondition>(ptr))
62
if((std::is_same<T, AndCondition>::value && std::dynamic_pointer_cast<NotEqualCondition>(ptr)) ||
63
(std::is_same<T, OrCondition>::value && std::dynamic_pointer_cast<EqualCondition>(ptr)))
65
_conds.emplace_back(ptr);
69
if(! ((dynamic_cast<UnfoldedIdentifierExpr*>((*comp)[0].get()) && (*comp)[1]->placeFree()) ||
70
(dynamic_cast<UnfoldedIdentifierExpr*>((*comp)[1].get()) && (*comp)[0]->placeFree())))
72
_conds.emplace_back(ptr);
76
std::vector<Condition_ptr> cnds{ptr};
77
auto cmp = std::make_shared<CompareConjunction>(cnds, std::is_same<T, OrCondition>::value);
78
tryMerge<T>(_conds, cmp, aggressive);
81
else if (auto conj = std::dynamic_pointer_cast<CompareConjunction>(ptr))
83
if((std::is_same<T, OrCondition>::value && ( conj->isNegated() || conj->singular())) ||
84
(std::is_same<T, AndCondition>::value && (!conj->isNegated() || conj->singular())))
86
if(auto lc = std::dynamic_pointer_cast<CompareConjunction>(_conds.size() == 0 ? nullptr : _conds[0]))
88
if(lc->isNegated() == std::is_same<T, OrCondition>::value)
90
auto cpy = std::make_shared<CompareConjunction>(*lc);
96
if(conj->isNegated() == std::is_same<T, OrCondition>::value)
97
_conds.insert(_conds.begin(), conj);
100
auto next = std::make_shared<CompareConjunction>(std::is_same<T, OrCondition>::value);
102
_conds.insert(_conds.begin(), next);
108
_conds.insert(_conds.begin(), conj);
113
_conds.emplace_back(ptr);
118
_conds.emplace_back(ptr);
123
template<typename T, bool K>
124
Condition_ptr makeLog(const std::vector<Condition_ptr>& conds, bool aggressive)
126
if(conds.size() == 0) return BooleanCondition::getShared(K);
127
if(conds.size() == 1) return conds[0];
129
std::vector<Condition_ptr> cnds;
130
for(auto& c : conds) tryMerge<T>(cnds, c, aggressive);
131
auto res = std::make_shared<T>(cnds);
132
if(res->singular()) return *res->begin();
133
if(res->empty()) return BooleanCondition::getShared(K);
137
Condition_ptr makeOr(const std::vector<Condition_ptr>& cptr)
138
{ return makeLog<OrCondition,false>(cptr, true); }
139
Condition_ptr makeAnd(const std::vector<Condition_ptr>& cptr)
140
{ return makeLog<AndCondition,true>(cptr, true); }
141
Condition_ptr makeOr(const Condition_ptr& a, const Condition_ptr& b) {
142
std::vector<Condition_ptr> cnds{a,b};
143
return makeLog<OrCondition,false>(cnds, true);
145
Condition_ptr makeAnd(const Condition_ptr& a, const Condition_ptr& b)
147
std::vector<Condition_ptr> cnds{a,b};
148
return makeLog<AndCondition,true>(cnds, true);
153
Condition_ptr BooleanCondition::FALSE_CONSTANT = std::make_shared<BooleanCondition>(false);
154
Condition_ptr BooleanCondition::TRUE_CONSTANT = std::make_shared<BooleanCondition>(true);
155
Condition_ptr DeadlockCondition::DEADLOCK = std::make_shared<DeadlockCondition>();
158
Condition_ptr BooleanCondition::getShared(bool val)
162
return TRUE_CONSTANT;
166
return FALSE_CONSTANT;
170
/******************** To String ********************/
172
void LiteralExpr::toString(std::ostream& out) const {
176
void UnfoldedIdentifierExpr::toString(std::ostream& out) const {
177
out << _name << "(P" << _offsetInMarking << ")";
180
void NaryExpr::toString(std::ostream& ss) const {
182
_exprs[0]->toString(ss);
183
for(size_t i = 1; i < _exprs.size(); ++i)
185
ss << " " << op() << " ";
186
_exprs[i]->toString(ss);
191
void CommutativeExpr::toString(std::ostream& ss) const {
192
ss << "( " << _constant;
194
ss << " " << op() << " " << i.second;
195
for(auto& e : _exprs)
197
ss << " " << op() << " ";
204
void MinusExpr::toString(std::ostream& out) const {
206
_expr->toString(out);
209
void SimpleQuantifierCondition::toString(std::ostream& out) const {
211
_cond->toString(out);
214
void UntilCondition::toString(std::ostream& out) const {
216
_cond1->toString(out);
218
_cond2->toString(out);
222
void LogicalCondition::toString(std::ostream& out) const {
224
_conds[0]->toString(out);
225
for(size_t i = 1; i < _conds.size(); ++i)
227
out << " " << op() << " ";
228
_conds[i]->toString(out);
233
void CompareConjunction::toString(std::ostream& out) const {
235
if(_negated) out << "not";
237
for(auto& c : _constraints)
239
if(!first) out << " and ";
241
out << "(" << c._lower << " <= " << c._name << ")";
242
if(c._lower != 0 && c._upper != std::numeric_limits<uint32_t>::max())
244
if(c._upper != std::numeric_limits<uint32_t>::max())
245
out << "(" << c._upper << " >= " << c._name << ")";
251
void CompareCondition::toString(std::ostream& out) const {
253
_expr1->toString(out);
254
out << " " << op() << " ";
255
_expr2->toString(out);
259
void NotCondition::toString(std::ostream& out) const {
261
_cond->toString(out);
265
void BooleanCondition::toString(std::ostream& out) const {
272
void DeadlockCondition::toString(std::ostream& out) const {
276
void StableMarkingCondition::_toString(std::ostream &out) const {
277
if(_compiled) _compiled->toString(out);
278
else out << "stable-marking";
281
void LivenessCondition::_toString(std::ostream &out) const {
282
if(_compiled) _compiled->toString(out);
283
else out << "liveness";
286
void QuasiLivenessCondition::_toString(std::ostream &out) const {
287
if(_compiled) _compiled->toString(out);
288
else out << "liveness";
291
void KSafeCondition::_toString(std::ostream &out) const {
292
if(_compiled) _compiled->toString(out);
296
_bound->toString(out);
301
void UpperBoundsCondition::_toString(std::ostream& out) const {
302
if(_compiled) _compiled->toString(out);
306
for(size_t i = 0; i < _places.size(); ++i)
308
if(i != 0) out << ", ";
315
void UnfoldedUpperBoundsCondition::toString(std::ostream& out) const {
317
for(size_t i = 0; i < _places.size(); ++i)
319
if(i != 0) out << ", ";
320
out << _places[i]._name;
325
void FireableCondition::_toString(std::ostream &out) const {
326
out << "is-fireable(" << _name << ")";
329
void UnfoldedFireableCondition::_toString(std::ostream &out) const {
330
out << "is-fireable(" << _name << ")";
333
/******************** To TAPAAL Query ********************/
335
void SimpleQuantifierCondition::toTAPAALQuery(std::ostream& out,TAPAALConditionExportContext& context) const {
337
_cond->toTAPAALQuery(out,context);
340
void UntilCondition::toTAPAALQuery(std::ostream& out,TAPAALConditionExportContext& context) const {
342
_cond1->toTAPAALQuery(out, context);
344
_cond2->toTAPAALQuery(out,context);
348
void LogicalCondition::toTAPAALQuery(std::ostream& out,TAPAALConditionExportContext& context) const {
350
_conds[0]->toTAPAALQuery(out, context);
351
for(size_t i = 1; i < _conds.size(); ++i)
353
out << " " << op() << " ";
354
_conds[i]->toTAPAALQuery(out, context);
359
void CompareConjunction::toTAPAALQuery(std::ostream& out,TAPAALConditionExportContext& context) const {
361
if(_negated) out << "!";
363
for(auto& c : _constraints)
365
if(!first) out << " and ";
367
out << "(" << c._lower << " <= " << context.netName << "." << c._name << ")";
368
if(c._lower != 0 && c._upper != std::numeric_limits<uint32_t>::max())
371
out << "(" << c._upper << " >= " << context.netName << "." << c._name << ")";
377
void CompareCondition::toTAPAALQuery(std::ostream& out,TAPAALConditionExportContext& context) const {
378
//If <id> <op> <literal>
379
if (_expr1->type() == Expr::IdentifierExpr && _expr2->type() == Expr::LiteralExpr) {
380
out << " ( " << context.netName << ".";
381
_expr1->toString(out);
382
out << " " << opTAPAAL() << " ";
383
_expr2->toString(out);
385
//If <literal> <op> <id>
386
} else if (_expr2->type() == Expr::IdentifierExpr && _expr1->type() == Expr::LiteralExpr) {
388
_expr1->toString(out);
389
out << " " << sopTAPAAL() << " " << context.netName << ".";
390
_expr2->toString(out);
393
context.failed = true;
398
void NotEqualCondition::toTAPAALQuery(std::ostream& out,TAPAALConditionExportContext& context) const {
400
CompareCondition::toTAPAALQuery(out,context);
404
void NotCondition::toTAPAALQuery(std::ostream& out,TAPAALConditionExportContext& context) const {
406
_cond->toTAPAALQuery(out,context);
410
void BooleanCondition::toTAPAALQuery(std::ostream& out,TAPAALConditionExportContext&) const {
417
void DeadlockCondition::toTAPAALQuery(std::ostream& out,TAPAALConditionExportContext&) const {
421
void UnfoldedUpperBoundsCondition::toTAPAALQuery(std::ostream& out, TAPAALConditionExportContext&) const {
423
for(size_t i = 0; i < _places.size(); ++i)
425
if(i != 0) out << ", ";
426
out << _places[i]._name;
431
/******************** opTAPAAL ********************/
433
std::string EqualCondition::opTAPAAL() const {
437
std::string NotEqualCondition::opTAPAAL() const {
439
} //Handled with hack in NotEqualCondition::toTAPAALQuery
441
std::string LessThanCondition::opTAPAAL() const {
445
std::string LessThanOrEqualCondition::opTAPAAL() const {
449
std::string GreaterThanCondition::opTAPAAL() const {
453
std::string GreaterThanOrEqualCondition::opTAPAAL() const {
457
std::string EqualCondition::sopTAPAAL() const {
461
std::string NotEqualCondition::sopTAPAAL() const {
463
} //Handled with hack in NotEqualCondition::toTAPAALQuery
465
std::string LessThanCondition::sopTAPAAL() const {
469
std::string LessThanOrEqualCondition::sopTAPAAL() const {
473
std::string GreaterThanCondition::sopTAPAAL() const {
477
std::string GreaterThanOrEqualCondition::sopTAPAAL() const {
481
/******************** Context Analysis ********************/
483
void NaryExpr::analyze(AnalysisContext& context) {
484
for(auto& e : _exprs) e->analyze(context);
487
void CommutativeExpr::analyze(AnalysisContext& context) {
490
AnalysisContext::ResolutionResult result = context.resolve(i.second);
491
if (result.success) {
492
i.first = result.offset;
494
ExprError error("Unable to resolve identifier \"" + i.second + "\"",
496
context.reportError(error);
499
NaryExpr::analyze(context);
500
std::sort(_ids.begin(), _ids.end(), [](auto& a, auto& b){ return a.first < b.first; });
501
std::sort(_exprs.begin(), _exprs.end(), [](auto& a, auto& b)
503
auto ida = dynamic_pointer_cast<PQL::UnfoldedIdentifierExpr>(a);
504
auto idb = dynamic_pointer_cast<PQL::UnfoldedIdentifierExpr>(b);
505
if(ida == NULL) return false;
506
if(ida && !idb) return true;
507
return ida->offset() < idb->offset();
511
void MinusExpr::analyze(AnalysisContext& context) {
512
_expr->analyze(context);
515
void LiteralExpr::analyze(AnalysisContext&) {
519
uint32_t getPlace(AnalysisContext& context, const std::string& name)
521
AnalysisContext::ResolutionResult result = context.resolve(name);
522
if (result.success) {
523
return result.offset;
525
ExprError error("Unable to resolve identifier \"" + name + "\"",
527
context.reportError(error);
532
Expr_ptr generateUnfoldedIdentifierExpr(ColoredAnalysisContext& context, std::unordered_map<uint32_t,std::string>& names, uint32_t colorIndex) {
533
std::string& place = names[colorIndex];
534
return std::make_shared<UnfoldedIdentifierExpr>(place, getPlace(context, place));
537
void IdentifierExpr::analyze(AnalysisContext &context) {
539
_compiled->analyze(context);
543
auto coloredContext = dynamic_cast<ColoredAnalysisContext*>(&context);
544
if(coloredContext != nullptr && coloredContext->isColored())
546
std::unordered_map<uint32_t,std::string> names;
547
if (!coloredContext->resolvePlace(_name, names)) {
548
ExprError error("Unable to resolve colored identifier \"" + _name + "\"", _name.length());
549
coloredContext->reportError(error);
552
if (names.size() == 1) {
553
_compiled = generateUnfoldedIdentifierExpr(*coloredContext, names, 0);
555
std::vector<Expr_ptr> identifiers;
556
for (auto& unfoldedName : names) {
557
identifiers.push_back(generateUnfoldedIdentifierExpr(*coloredContext,names,unfoldedName.first));
559
_compiled = std::make_shared<PQL::PlusExpr>(std::move(identifiers));
562
_compiled = std::make_shared<UnfoldedIdentifierExpr>(_name, getPlace(context, _name));
564
_compiled->analyze(context);
567
void UnfoldedIdentifierExpr::analyze(AnalysisContext& context) {
568
AnalysisContext::ResolutionResult result = context.resolve(_name);
569
if (result.success) {
570
_offsetInMarking = result.offset;
572
ExprError error("Unable to resolve identifier \"" + _name + "\"",
574
context.reportError(error);
578
void SimpleQuantifierCondition::analyze(AnalysisContext& context) {
579
_cond->analyze(context);
582
void UntilCondition::analyze(AnalysisContext& context) {
583
_cond1->analyze(context);
584
_cond2->analyze(context);
587
void LogicalCondition::analyze(AnalysisContext& context) {
588
for(auto& c : _conds) c->analyze(context);
591
void UnfoldedFireableCondition::_analyze(AnalysisContext& context)
593
std::vector<Condition_ptr> conds;
594
AnalysisContext::ResolutionResult result = context.resolve(_name, false);
597
ExprError error("Unable to resolve identifier \"" + _name + "\"",
599
context.reportError(error);
602
assert(_name.compare(context.net()->transitionNames()[result.offset]) == 0);
603
auto preset = context.net()->preset(result.offset);
604
for(; preset.first != preset.second; ++preset.first)
606
assert(preset.first->place != std::numeric_limits<uint32_t>::max());
607
assert(preset.first->place != -1);
608
auto id = std::make_shared<UnfoldedIdentifierExpr>(context.net()->placeNames()[preset.first->place], preset.first->place);
609
auto lit = std::make_shared<LiteralExpr>(preset.first->tokens);
611
if(!preset.first->inhibitor)
613
conds.emplace_back(std::make_shared<GreaterThanOrEqualCondition>(id, lit));
615
else if(preset.first->tokens > 0)
617
conds.emplace_back(std::make_shared<LessThanCondition>(id, lit));
620
if(conds.size() == 1) _compiled = conds[0];
621
else _compiled = std::make_shared<AndCondition>(conds);
622
_compiled->analyze(context);
625
void FireableCondition::_analyze(AnalysisContext &context) {
627
auto coloredContext = dynamic_cast<ColoredAnalysisContext*>(&context);
628
if(coloredContext != nullptr && coloredContext->isColored()) {
629
std::vector<std::string> names;
630
if (!coloredContext->resolveTransition(_name, names)) {
631
ExprError error("Unable to resolve colored identifier \"" + _name + "\"", _name.length());
632
coloredContext->reportError(error);
635
if (names.size() == 1) {
636
_compiled = std::make_shared<UnfoldedFireableCondition>(names[0]);
638
std::vector<Condition_ptr> identifiers;
639
for (auto& unfoldedName : names) {
640
identifiers.push_back(std::make_shared<UnfoldedFireableCondition>(unfoldedName));
642
_compiled = std::make_shared<OrCondition>(std::move(identifiers));
645
_compiled = std::make_shared<UnfoldedFireableCondition>(_name);
647
_compiled->analyze(context);
650
void CompareConjunction::analyze(AnalysisContext& context) {
651
for(auto& c : _constraints){
652
c._place = getPlace(context, c._name);
653
assert(c._place >= 0);
655
std::sort(std::begin(_constraints), std::end(_constraints));
658
void CompareCondition::analyze(AnalysisContext& context) {
659
_expr1->analyze(context);
660
_expr2->analyze(context);
663
void NotCondition::analyze(AnalysisContext& context) {
664
_cond->analyze(context);
667
void BooleanCondition::analyze(AnalysisContext&) {
670
void DeadlockCondition::analyze(AnalysisContext& c) {
674
void KSafeCondition::_analyze(AnalysisContext &context) {
675
auto coloredContext = dynamic_cast<ColoredAnalysisContext*>(&context);
676
std::vector<Condition_ptr> k_safe;
677
if(coloredContext != nullptr && coloredContext->isColored())
679
for(auto& p : coloredContext->allColoredPlaceNames())
680
k_safe.emplace_back(std::make_shared<LessThanOrEqualCondition>(std::make_shared<IdentifierExpr>(p.first), _bound));
684
for(auto& p : context.allPlaceNames())
685
k_safe.emplace_back(std::make_shared<LessThanOrEqualCondition>(std::make_shared<UnfoldedIdentifierExpr>(p.first), _bound));
687
_compiled = std::make_shared<AGCondition>(std::make_shared<AndCondition>(std::move(k_safe)));
688
_compiled->analyze(context);
691
void QuasiLivenessCondition::_analyze(AnalysisContext &context)
693
auto coloredContext = dynamic_cast<ColoredAnalysisContext*>(&context);
694
std::vector<Condition_ptr> quasi;
695
if(coloredContext != nullptr && coloredContext->isColored())
697
for(auto& n : coloredContext->allColoredTransitionNames())
699
std::vector<Condition_ptr> disj;
700
for(auto& tn : n.second)
701
disj.emplace_back(std::make_shared<UnfoldedFireableCondition>(tn));
702
quasi.emplace_back(std::make_shared<EFCondition>(std::make_shared<OrCondition>(std::move(disj))));
707
for(auto& n : context.allTransitionNames())
709
quasi.emplace_back(std::make_shared<EFCondition>(std::make_shared<UnfoldedFireableCondition>(n.first)));
712
_compiled = std::make_shared<AndCondition>(std::move(quasi));
713
_compiled->analyze(context);
716
void LivenessCondition::_analyze(AnalysisContext &context)
718
auto coloredContext = dynamic_cast<ColoredAnalysisContext*>(&context);
719
std::vector<Condition_ptr> liveness;
720
if(coloredContext != nullptr && coloredContext->isColored())
722
for(auto& n : coloredContext->allColoredTransitionNames())
724
std::vector<Condition_ptr> disj;
725
for(auto& tn : n.second)
726
disj.emplace_back(std::make_shared<UnfoldedFireableCondition>(tn));
727
liveness.emplace_back(std::make_shared<AGCondition>(std::make_shared<EFCondition>(std::make_shared<OrCondition>(std::move(disj)))));
732
for(auto& n : context.allTransitionNames())
734
liveness.emplace_back(std::make_shared<AGCondition>(std::make_shared<EFCondition>(std::make_shared<UnfoldedFireableCondition>(n.first))));
737
_compiled = std::make_shared<AndCondition>(std::move(liveness));
738
_compiled->analyze(context);
741
void StableMarkingCondition::_analyze(AnalysisContext &context)
743
auto coloredContext = dynamic_cast<ColoredAnalysisContext*>(&context);
744
std::vector<Condition_ptr> stable_check;
745
if(coloredContext != nullptr && coloredContext->isColored())
747
for(auto& cpn : coloredContext->allColoredPlaceNames())
749
std::vector<Expr_ptr> sum;
750
MarkVal init_marking = 0;
751
for(auto& pn : cpn.second)
753
auto id = std::make_shared<UnfoldedIdentifierExpr>(pn.second);
754
id->analyze(context);
755
init_marking += context.net()->initial(id->offset());
756
sum.emplace_back(std::move(id));
759
stable_check.emplace_back(std::make_shared<AGCondition>(std::make_shared<EqualCondition>(
760
std::make_shared<PlusExpr>(std::move(sum)),
761
std::make_shared<LiteralExpr>(init_marking))));
767
for(auto& p : context.net()->placeNames())
769
stable_check.emplace_back(std::make_shared<AGCondition>(std::make_shared<EqualCondition>(
770
std::make_shared<UnfoldedIdentifierExpr>(p, i),
771
std::make_shared<LiteralExpr>(context.net()->initial(i)))));
775
_compiled = std::make_shared<OrCondition>(std::move(stable_check));
776
_compiled->analyze(context);
779
void UpperBoundsCondition::_analyze(AnalysisContext& context)
781
auto coloredContext = dynamic_cast<ColoredAnalysisContext*>(&context);
782
if(coloredContext != nullptr && coloredContext->isColored())
784
std::vector<std::string> uplaces;
785
for(auto& p : _places)
787
std::unordered_map<uint32_t,std::string> names;
788
if (!coloredContext->resolvePlace(p, names)) {
789
ExprError error("Unable to resolve colored identifier \"" + p + "\"", p.length());
790
coloredContext->reportError(error);
793
for(auto& id : names)
795
uplaces.push_back(names[id.first]);
798
_compiled = std::make_shared<UnfoldedUpperBoundsCondition>(uplaces);
800
_compiled = std::make_shared<UnfoldedUpperBoundsCondition>(_places);
802
_compiled->analyze(context);
805
void UnfoldedUpperBoundsCondition::analyze(AnalysisContext& c)
807
for(auto& p : _places)
809
AnalysisContext::ResolutionResult result = c.resolve(p._name);
810
if (result.success) {
811
p._place = result.offset;
813
ExprError error("Unable to resolve identifier \"" + p._name + "\"",
815
c.reportError(error);
818
std::sort(_places.begin(), _places.end());
821
/******************** Evaluation ********************/
823
int NaryExpr::evaluate(const EvaluationContext& context) {
824
int32_t r = preOp(context);
825
for(size_t i = 1; i < _exprs.size(); ++i)
827
r = apply(r, _exprs[i]->evalAndSet(context));
832
int32_t NaryExpr::preOp(const EvaluationContext& context) const {
833
return _exprs[0]->evaluate(context);
836
int32_t CommutativeExpr::preOp(const EvaluationContext& context) const {
837
int32_t res = _constant;
838
for(auto& i : _ids) res = this->apply(res, context.marking()[i.first]);
839
if(_exprs.size() > 0) res = this->apply(res, _exprs[0]->evalAndSet(context));
843
int CommutativeExpr::evaluate(const EvaluationContext& context) {
844
if(_exprs.size() == 0) return preOp(context);
845
return NaryExpr::evaluate(context);
848
int MinusExpr::evaluate(const EvaluationContext& context) {
849
return -(_expr->evaluate(context));
852
int LiteralExpr::evaluate(const EvaluationContext&) {
856
int UnfoldedIdentifierExpr::evaluate(const EvaluationContext& context) {
857
assert(_offsetInMarking != -1);
858
return context.marking()[_offsetInMarking];
861
Condition::Result SimpleQuantifierCondition::evaluate(const EvaluationContext& context) {
865
Condition::Result EGCondition::evaluate(const EvaluationContext& context) {
866
if(_cond->evaluate(context) == RFALSE) return RFALSE;
870
Condition::Result AGCondition::evaluate(const EvaluationContext& context)
872
if(_cond->evaluate(context) == RFALSE) return RFALSE;
876
Condition::Result EFCondition::evaluate(const EvaluationContext& context) {
877
if(_cond->evaluate(context) == RTRUE) return RTRUE;
881
Condition::Result AFCondition::evaluate(const EvaluationContext& context) {
882
if(_cond->evaluate(context) == RTRUE) return RTRUE;
887
Condition::Result UntilCondition::evaluate(const EvaluationContext& context) {
888
auto r2 = _cond2->evaluate(context);
889
if(r2 != RFALSE) return r2;
890
auto r1 = _cond1->evaluate(context);
900
Condition::Result AndCondition::evaluate(const EvaluationContext& context) {
902
for(auto& c : _conds)
904
auto r = c->evaluate(context);
905
if(r == RFALSE) return RFALSE;
906
else if(r == RUNKNOWN) res = RUNKNOWN;
911
Condition::Result OrCondition::evaluate(const EvaluationContext& context) {
913
for(auto& c : _conds)
915
auto r = c->evaluate(context);
916
if(r == RTRUE) return RTRUE;
917
else if(r == RUNKNOWN) res = RUNKNOWN;
922
Condition::Result CompareConjunction::evaluate(const EvaluationContext& context){
923
// auto rres = _org->evaluate(context);
925
for(auto& c : _constraints)
927
res = res && context.marking()[c._place] <= c._upper &&
928
context.marking()[c._place] >= c._lower;
931
return (_negated xor res) ? RTRUE : RFALSE;
934
Condition::Result CompareCondition::evaluate(const EvaluationContext& context) {
935
int v1 = _expr1->evaluate(context);
936
int v2 = _expr2->evaluate(context);
937
return apply(v1, v2) ? RTRUE : RFALSE;
940
Condition::Result NotCondition::evaluate(const EvaluationContext& context) {
941
auto res = _cond->evaluate(context);
942
if(res != RUNKNOWN) return res == RFALSE ? RTRUE : RFALSE;
946
Condition::Result BooleanCondition::evaluate(const EvaluationContext&) {
947
return _value ? RTRUE : RFALSE;
950
Condition::Result DeadlockCondition::evaluate(const EvaluationContext& context) {
953
if (!context.net()->deadlocked(context.marking())) {
959
size_t UnfoldedUpperBoundsCondition::value(const MarkVal* marking)
962
for(auto& p : _places)
964
auto val = marking[p._place];
965
p._maxed_out = (p._max <= val);
971
Condition::Result UnfoldedUpperBoundsCondition::evaluate(const EvaluationContext& context) {
972
setUpperBound(value(context.marking()));
973
return _max <= _bound ? RTRUE : RUNKNOWN;
976
/******************** Evaluation - save result ********************/
977
Condition::Result SimpleQuantifierCondition::evalAndSet(const EvaluationContext& context) {
981
Condition::Result EGCondition::evalAndSet(const EvaluationContext& context) {
982
auto res = _cond->evalAndSet(context);
983
if(res != RFALSE) res = RUNKNOWN;
988
Condition::Result AGCondition::evalAndSet(const EvaluationContext& context) {
989
auto res = _cond->evalAndSet(context);
990
if(res != RFALSE) res = RUNKNOWN;
995
Condition::Result EFCondition::evalAndSet(const EvaluationContext& context) {
996
auto res = _cond->evalAndSet(context);
997
if(res != RTRUE) res = RUNKNOWN;
1002
Condition::Result AFCondition::evalAndSet(const EvaluationContext& context) {
1003
auto res = _cond->evalAndSet(context);
1004
if(res != RTRUE) res = RUNKNOWN;
1009
Condition::Result UntilCondition::evalAndSet(const EvaluationContext& context) {
1010
auto r2 = _cond2->evalAndSet(context);
1011
if(r2 != RFALSE) return r2;
1012
auto r1 = _cond1->evalAndSet(context);
1013
if(r1 == RFALSE) return RFALSE;
1017
int Expr::evalAndSet(const EvaluationContext& context) {
1018
int r = evaluate(context);
1023
Condition::Result AndCondition::evalAndSet(const EvaluationContext& context) {
1025
for(auto& c : _conds)
1027
auto r = c->evalAndSet(context);
1033
else if(r == RUNKNOWN)
1042
Condition::Result OrCondition::evalAndSet(const EvaluationContext& context) {
1043
Result res = RFALSE;
1044
for(auto& c : _conds)
1046
auto r = c->evalAndSet(context);
1052
else if(r == RUNKNOWN)
1061
Condition::Result CompareConjunction::evalAndSet(const EvaluationContext& context)
1063
auto res = evaluate(context);
1068
Condition::Result CompareCondition::evalAndSet(const EvaluationContext& context) {
1069
int v1 = _expr1->evalAndSet(context);
1070
int v2 = _expr2->evalAndSet(context);
1071
bool res = apply(v1, v2);
1073
return res ? RTRUE : RFALSE;
1076
Condition::Result NotCondition::evalAndSet(const EvaluationContext& context) {
1077
auto res = _cond->evalAndSet(context);
1078
if(res != RUNKNOWN) res = res == RFALSE ? RTRUE : RFALSE;
1083
Condition::Result BooleanCondition::evalAndSet(const EvaluationContext&) {
1084
setSatisfied(_value);
1085
return _value ? RTRUE : RFALSE;
1088
Condition::Result DeadlockCondition::evalAndSet(const EvaluationContext& context) {
1091
setSatisfied(context.net()->deadlocked(context.marking()));
1092
return isSatisfied() ? RTRUE : RFALSE;
1095
Condition::Result UnfoldedUpperBoundsCondition::evalAndSet(const EvaluationContext& context)
1097
auto res = evaluate(context);
1102
/******************** Range Contexts ********************/
1105
void EGCondition::visit(Visitor& ctx) const
1107
ctx.accept<decltype(this)>(this);
1110
void EUCondition::visit(Visitor& ctx) const
1112
ctx.accept<decltype(this)>(this);
1115
void EXCondition::visit(Visitor& ctx) const
1117
ctx.accept<decltype(this)>(this);
1120
void EFCondition::visit(Visitor& ctx) const
1122
ctx.accept<decltype(this)>(this);
1125
void AUCondition::visit(Visitor& ctx) const
1127
ctx.accept<decltype(this)>(this);
1130
void AXCondition::visit(Visitor& ctx) const
1132
ctx.accept<decltype(this)>(this);
1135
void AFCondition::visit(Visitor& ctx) const
1137
ctx.accept<decltype(this)>(this);
1140
void AGCondition::visit(Visitor& ctx) const
1142
ctx.accept<decltype(this)>(this);
1145
void AndCondition::visit(Visitor& ctx) const
1147
ctx.accept<decltype(this)>(this);
1150
void OrCondition::visit(Visitor& ctx) const
1152
ctx.accept<decltype(this)>(this);
1155
void NotCondition::visit(Visitor& ctx) const
1157
ctx.accept<decltype(this)>(this);
1160
void EqualCondition::visit(Visitor& ctx) const
1162
ctx.accept<decltype(this)>(this);
1165
void NotEqualCondition::visit(Visitor& ctx) const
1167
ctx.accept<decltype(this)>(this);
1170
void CompareConjunction::visit(Visitor& ctx) const
1172
ctx.accept<decltype(this)>(this);
1175
void GreaterThanOrEqualCondition::visit(Visitor& ctx) const
1177
ctx.accept<decltype(this)>(this);
1180
void LessThanOrEqualCondition::visit(Visitor& ctx) const
1182
ctx.accept<decltype(this)>(this);
1185
void GreaterThanCondition::visit(Visitor& ctx) const
1187
ctx.accept<decltype(this)>(this);
1190
void LessThanCondition::visit(Visitor& ctx) const
1192
ctx.accept<decltype(this)>(this);
1195
void BooleanCondition::visit(Visitor& ctx) const
1197
ctx.accept<decltype(this)>(this);
1200
void DeadlockCondition::visit(Visitor& ctx) const
1202
ctx.accept<decltype(this)>(this);
1205
void StableMarkingCondition::visit(Visitor& ctx) const
1208
_compiled->visit(ctx);
1210
ctx.accept<decltype(this)>(this);
1213
void QuasiLivenessCondition::visit(Visitor& ctx) const
1216
_compiled->visit(ctx);
1218
ctx.accept<decltype(this)>(this);
1221
void KSafeCondition::visit(Visitor& ctx) const
1224
_compiled->visit(ctx);
1226
ctx.accept<decltype(this)>(this);
1229
void LivenessCondition::visit(Visitor& ctx) const
1232
_compiled->visit(ctx);
1234
ctx.accept<decltype(this)>(this);
1237
void FireableCondition::visit(Visitor& ctx) const
1240
_compiled->visit(ctx);
1242
ctx.accept<decltype(this)>(this);
1245
void UpperBoundsCondition::visit(Visitor& ctx) const
1248
_compiled->visit(ctx);
1250
ctx.accept<decltype(this)>(this);
1253
void UnfoldedFireableCondition::visit(Visitor& ctx) const
1256
_compiled->visit(ctx);
1258
ctx.accept<decltype(this)>(this);
1262
void UnfoldedUpperBoundsCondition::visit(Visitor& ctx) const
1264
ctx.accept<decltype(this)>(this);
1267
void LiteralExpr::visit(Visitor& ctx) const
1269
ctx.accept<decltype(this)>(this);
1272
void IdentifierExpr::visit(Visitor& ctx) const
1275
_compiled->visit(ctx);
1277
ctx.accept<decltype(this)>(this);
1280
void UnfoldedIdentifierExpr::visit(Visitor& ctx) const
1282
ctx.accept<decltype(this)>(this);
1285
void MinusExpr::visit(Visitor& ctx) const
1287
ctx.accept<decltype(this)>(this);
1290
void SubtractExpr::visit(Visitor& ctx) const
1292
ctx.accept<decltype(this)>(this);
1295
void PlusExpr::visit(Visitor& ctx) const
1297
ctx.accept<decltype(this)>(this);
1300
void MultiplyExpr::visit(Visitor& ctx) const
1302
ctx.accept<decltype(this)>(this);
1305
/******************** Apply (BinaryExpr subclasses) ********************/
1307
int PlusExpr::apply(int v1, int v2) const {
1311
int SubtractExpr::apply(int v1, int v2) const {
1315
int MultiplyExpr::apply(int v1, int v2) const {
1319
/******************** Apply (CompareCondition subclasses) ********************/
1321
bool EqualCondition::apply(int v1, int v2) const {
1325
bool NotEqualCondition::apply(int v1, int v2) const {
1329
bool LessThanCondition::apply(int v1, int v2) const {
1333
bool LessThanOrEqualCondition::apply(int v1, int v2) const {
1337
bool GreaterThanCondition::apply(int v1, int v2) const {
1341
bool GreaterThanOrEqualCondition::apply(int v1, int v2) const {
1345
/******************** Op (BinaryExpr subclasses) ********************/
1347
std::string PlusExpr::op() const {
1351
std::string SubtractExpr::op() const {
1355
std::string MultiplyExpr::op() const {
1359
/******************** Op (QuantifierCondition subclasses) ********************/
1361
std::string EXCondition::op() const {
1365
std::string EGCondition::op() const {
1369
std::string EFCondition::op() const {
1373
std::string AXCondition::op() const {
1377
std::string AGCondition::op() const {
1381
std::string AFCondition::op() const {
1385
/******************** Op (UntilCondition subclasses) ********************/
1387
std::string EUCondition::op() const {
1391
std::string AUCondition::op() const {
1395
/******************** Op (LogicalCondition subclasses) ********************/
1397
std::string AndCondition::op() const {
1401
std::string OrCondition::op() const {
1405
/******************** Op (CompareCondition subclasses) ********************/
1407
std::string EqualCondition::op() const {
1411
std::string NotEqualCondition::op() const {
1415
std::string LessThanCondition::op() const {
1419
std::string LessThanOrEqualCondition::op() const {
1423
std::string GreaterThanCondition::op() const {
1427
std::string GreaterThanOrEqualCondition::op() const {
1431
/******************** free of places ********************/
1433
bool NaryExpr::placeFree() const
1435
for(auto& e : _exprs)
1441
bool CommutativeExpr::placeFree() const
1443
if(_ids.size() > 0) return false;
1444
return NaryExpr::placeFree();
1447
bool MinusExpr::placeFree() const
1449
return _expr->placeFree();
1452
/******************** Expr::type() implementation ********************/
1454
Expr::Types PlusExpr::type() const {
1455
return Expr::PlusExpr;
1458
Expr::Types SubtractExpr::type() const {
1459
return Expr::SubtractExpr;
1462
Expr::Types MultiplyExpr::type() const {
1463
return Expr::MinusExpr;
1466
Expr::Types MinusExpr::type() const {
1467
return Expr::MinusExpr;
1470
Expr::Types LiteralExpr::type() const {
1471
return Expr::LiteralExpr;
1474
Expr::Types UnfoldedIdentifierExpr::type() const {
1475
return Expr::IdentifierExpr;
1478
/******************** Distance Condition ********************/
1480
#define MAX(v1, v2) (v1 > v2 ? v1 : v2)
1481
#define MIN(v1, v2) (v1 < v2 ? v1 : v2)
1484
uint32_t delta<EqualCondition>(int v1, int v2, bool negated) {
1486
return std::abs(v1 - v2);
1488
return v1 == v2 ? 1 : 0;
1492
uint32_t delta<NotEqualCondition>(int v1, int v2, bool negated) {
1493
return delta<EqualCondition>(v1, v2, !negated);
1497
uint32_t delta<LessThanCondition>(int v1, int v2, bool negated) {
1499
return v1 < v2 ? 0 : v1 - v2 + 1;
1501
return v1 >= v2 ? 0 : v2 - v1;
1505
uint32_t delta<LessThanOrEqualCondition>(int v1, int v2, bool negated) {
1507
return v1 <= v2 ? 0 : v1 - v2;
1509
return v1 > v2 ? 0 : v2 - v1 + 1;
1513
uint32_t delta<GreaterThanCondition>(int v1, int v2, bool negated) {
1514
return delta<LessThanOrEqualCondition>(v1, v2, !negated);
1518
uint32_t delta<GreaterThanOrEqualCondition>(int v1, int v2, bool negated) {
1519
return delta<LessThanCondition>(v1, v2, !negated);
1522
uint32_t NotCondition::distance(DistanceContext& context) const {
1524
uint32_t retval = _cond->distance(context);
1529
uint32_t BooleanCondition::distance(DistanceContext& context) const {
1530
if (context.negated() != _value)
1532
return std::numeric_limits<uint32_t>::max();
1535
uint32_t DeadlockCondition::distance(DistanceContext& context) const {
1539
uint32_t UnfoldedUpperBoundsCondition::distance(DistanceContext& context) const
1542
for(auto& p : _places)
1544
tmp += context.marking()[p._place];
1550
uint32_t EFCondition::distance(DistanceContext& context) const {
1551
return _cond->distance(context);
1554
uint32_t EGCondition::distance(DistanceContext& context) const {
1555
return _cond->distance(context);
1558
uint32_t EXCondition::distance(DistanceContext& context) const {
1559
return _cond->distance(context);
1562
uint32_t EUCondition::distance(DistanceContext& context) const {
1563
return _cond2->distance(context);
1566
uint32_t AFCondition::distance(DistanceContext& context) const {
1568
uint32_t retval = _cond->distance(context);
1573
uint32_t AXCondition::distance(DistanceContext& context) const {
1575
uint32_t retval = _cond->distance(context);
1580
uint32_t AGCondition::distance(DistanceContext& context) const {
1582
uint32_t retval = _cond->distance(context);
1587
uint32_t AUCondition::distance(DistanceContext& context) const {
1589
auto r1 = _cond1->distance(context);
1590
auto r2 = _cond2->distance(context);
1595
uint32_t LogicalCondition::distance(DistanceContext& context) const {
1596
uint32_t d = _conds[0]->distance(context);
1597
for(size_t i = 1; i < _conds.size(); ++i) d = delta(d, _conds[i]->distance(context), context);
1601
uint32_t CompareConjunction::distance(DistanceContext& context) const {
1603
auto neg = context.negated() != _negated;
1606
for(auto& c : _constraints)
1608
auto pv = context.marking()[c._place];
1609
d += (c._upper == std::numeric_limits<uint32_t>::max() ? 0 : delta<LessThanOrEqualCondition>(pv, c._upper, neg)) +
1610
(c._lower == 0 ? 0 : delta<GreaterThanOrEqualCondition>(pv, c._lower, neg));
1616
for(auto& c : _constraints)
1618
auto pv = context.marking()[c._place];
1619
if(c._upper != std::numeric_limits<uint32_t>::max())
1621
auto d2 = delta<LessThanOrEqualCondition>(pv, c._upper, neg);
1623
else d = MIN(d, d2);
1629
auto d2 = delta<GreaterThanOrEqualCondition>(pv, c._upper, neg);
1631
else d = MIN(d, d2);
1639
uint32_t AndCondition::delta(uint32_t d1,
1641
const DistanceContext& context) const {
1645
uint32_t OrCondition::delta(uint32_t d1,
1647
const DistanceContext& context) const {
1648
if (context.negated())
1659
uint32_t LessThanOrEqualCondition::distance(DistanceContext& context) const {
1660
return _distance(context, delta<LessThanOrEqualCondition>);
1663
uint32_t GreaterThanOrEqualCondition::distance(DistanceContext& context) const {
1664
return _distance(context, delta<GreaterThanOrEqualCondition>);
1667
uint32_t LessThanCondition::distance(DistanceContext& context) const {
1668
return _distance(context, delta<LessThanCondition>);
1671
uint32_t GreaterThanCondition::distance(DistanceContext& context) const {
1672
return _distance(context, delta<GreaterThanCondition>);
1675
uint32_t NotEqualCondition::distance(DistanceContext& context) const {
1676
return _distance(context, delta<NotEqualCondition>);
1679
uint32_t EqualCondition::distance(DistanceContext& context) const {
1680
return _distance(context, delta<EqualCondition>);
1683
/******************** BIN output ********************/
1685
void LiteralExpr::toBinary(std::ostream& out) const {
1686
out.write("l", sizeof(char));
1687
out.write(reinterpret_cast<const char*>(&_value), sizeof(int));
1690
void UnfoldedIdentifierExpr::toBinary(std::ostream& out) const {
1691
out.write("i", sizeof(char));
1692
out.write(reinterpret_cast<const char*>(&_offsetInMarking), sizeof(int));
1695
void MinusExpr::toBinary(std::ostream& out) const
1697
auto e1 = std::make_shared<PQL::LiteralExpr>(0);
1698
std::vector<Expr_ptr> exprs;
1699
exprs.push_back(e1);
1700
exprs.push_back(_expr);
1701
PQL::SubtractExpr(std::move(exprs)).toBinary(out);
1704
void SubtractExpr::toBinary(std::ostream& out) const {
1705
out.write("-", sizeof(char));
1706
uint32_t size = _exprs.size();
1707
out.write(reinterpret_cast<const char*>(&size), sizeof(uint32_t));
1708
for(auto& e : _exprs)
1712
void CommutativeExpr::toBinary(std::ostream& out) const
1715
out.write(&sop[0], sizeof(char));
1716
out.write(reinterpret_cast<const char*>(&_constant), sizeof(int32_t));
1717
uint32_t size = _ids.size();
1718
out.write(reinterpret_cast<const char*>(&size), sizeof(uint32_t));
1719
size = _exprs.size();
1720
out.write(reinterpret_cast<const char*>(&size), sizeof(uint32_t));
1721
for(auto& id : _ids)
1722
out.write(reinterpret_cast<const char*>(&id.first), sizeof(uint32_t));
1723
for(auto& e : _exprs)
1727
void SimpleQuantifierCondition::toBinary(std::ostream& out) const
1729
auto path = getPath();
1730
auto quant = getQuantifier();
1731
out.write(reinterpret_cast<const char*>(&path), sizeof(Path));
1732
out.write(reinterpret_cast<const char*>(&quant), sizeof(Quantifier));
1733
_cond->toBinary(out);
1736
void UntilCondition::toBinary(std::ostream& out) const
1738
auto path = getPath();
1739
auto quant = getQuantifier();
1740
out.write(reinterpret_cast<const char*>(&path), sizeof(Path));
1741
out.write(reinterpret_cast<const char*>(&quant), sizeof(Quantifier));
1742
_cond1->toBinary(out);
1743
_cond2->toBinary(out);
1746
void LogicalCondition::toBinary(std::ostream& out) const
1748
auto path = getPath();
1749
auto quant = getQuantifier();
1750
out.write(reinterpret_cast<const char*>(&path), sizeof(Path));
1751
out.write(reinterpret_cast<const char*>(&quant), sizeof(Quantifier));
1752
uint32_t size = _conds.size();
1753
out.write(reinterpret_cast<const char*>(&size), sizeof(uint32_t));
1754
for(auto& c : _conds) c->toBinary(out);
1757
void CompareConjunction::toBinary(std::ostream& out) const
1759
auto path = getPath();
1760
auto quant = Quantifier::COMPCONJ;
1761
out.write(reinterpret_cast<const char*>(&path), sizeof(Path));
1762
out.write(reinterpret_cast<const char*>(&quant), sizeof(Quantifier));
1763
out.write(reinterpret_cast<const char*>(&_negated), sizeof(bool));
1764
uint32_t size = _constraints.size();
1765
out.write(reinterpret_cast<const char*>(&size), sizeof(uint32_t));
1766
for(auto& c : _constraints)
1768
out.write(reinterpret_cast<const char*>(&c._place), sizeof(int32_t));
1769
out.write(reinterpret_cast<const char*>(&c._lower), sizeof(uint32_t));
1770
out.write(reinterpret_cast<const char*>(&c._upper), sizeof(uint32_t));
1774
void CompareCondition::toBinary(std::ostream& out) const
1776
auto path = getPath();
1777
auto quant = getQuantifier();
1778
out.write(reinterpret_cast<const char*>(&path), sizeof(Path));
1779
out.write(reinterpret_cast<const char*>(&quant), sizeof(Quantifier));
1780
std::string sop = op();
1781
out.write(sop.data(), sop.size());
1782
out.write("\0", sizeof(char));
1783
_expr1->toBinary(out);
1784
_expr2->toBinary(out);
1787
void DeadlockCondition::toBinary(std::ostream& out) const
1789
auto path = getPath();
1790
auto quant = Quantifier::DEADLOCK;
1791
out.write(reinterpret_cast<const char*>(&path), sizeof(Path));
1792
out.write(reinterpret_cast<const char*>(&quant), sizeof(Quantifier));
1795
void BooleanCondition::toBinary(std::ostream& out) const
1797
auto path = getPath();
1798
auto quant = Quantifier::PN_BOOLEAN;
1799
out.write(reinterpret_cast<const char*>(&path), sizeof(Path));
1800
out.write(reinterpret_cast<const char*>(&quant), sizeof(Quantifier));
1801
out.write(reinterpret_cast<const char*>(&_value), sizeof(bool));
1804
void UnfoldedUpperBoundsCondition::toBinary(std::ostream& out) const
1806
auto path = getPath();
1807
auto quant = Quantifier::UPPERBOUNDS;
1808
out.write(reinterpret_cast<const char*>(&path), sizeof(Path));
1809
out.write(reinterpret_cast<const char*>(&quant), sizeof(Quantifier));
1810
uint32_t size = _places.size();
1811
out.write(reinterpret_cast<const char*>(&size), sizeof(uint32_t));
1812
out.write(reinterpret_cast<const char*>(&_max), sizeof(double));
1813
out.write(reinterpret_cast<const char*>(&_offset), sizeof(double));
1814
for(auto& b : _places)
1816
out.write(reinterpret_cast<const char*>(&b._place), sizeof(uint32_t));
1817
out.write(reinterpret_cast<const char*>(&b._max), sizeof(double));
1821
void NotCondition::toBinary(std::ostream& out) const
1823
auto path = getPath();
1824
auto quant = getQuantifier();
1825
out.write(reinterpret_cast<const char*>(&path), sizeof(Path));
1826
out.write(reinterpret_cast<const char*>(&quant), sizeof(Quantifier));
1827
_cond->toBinary(out);
1830
/******************** CTL Output ********************/
1832
void LiteralExpr::toXML(std::ostream& out,uint32_t tabs, bool tokencount) const {
1833
generateTabs(out,tabs) << "<integer-constant>" + std::to_string(_value) + "</integer-constant>\n";
1836
void UnfoldedIdentifierExpr::toXML(std::ostream& out,uint32_t tabs, bool tokencount) const {
1838
generateTabs(out,tabs) << "<place>" << _name << "</place>\n";
1842
generateTabs(out,tabs) << "<tokens-count>\n";
1843
generateTabs(out,tabs+1) << "<place>" << _name << "</place>\n";
1844
generateTabs(out,tabs) << "</tokens-count>\n";
1848
void PlusExpr::toXML(std::ostream& ss,uint32_t tabs, bool tokencount) const {
1850
for(auto& e : _exprs) e->toXML(ss,tabs, tokencount);
1855
generateTabs(ss,tabs) << "<tokens-count>\n";
1856
for(auto& e : _ids) generateTabs(ss,tabs+1) << "<place>" << e.second << "</place>\n";
1857
for(auto& e : _exprs) e->toXML(ss,tabs+1, true);
1858
generateTabs(ss,tabs) << "</tokens-count>\n";
1861
generateTabs(ss,tabs) << "<integer-sum>\n";
1862
generateTabs(ss,tabs+1) << "<integer-constant>" + std::to_string(_constant) + "</integer-constant>\n";
1865
generateTabs(ss,tabs+1) << "<tokens-count>\n";
1866
generateTabs(ss,tabs+2) << "<place>" << i.second << "</place>\n";
1867
generateTabs(ss,tabs+1) << "</tokens-count>\n";
1869
for(auto& e : _exprs) e->toXML(ss,tabs+1, tokencount);
1870
generateTabs(ss,tabs) << "</integer-sum>\n";
1873
void SubtractExpr::toXML(std::ostream& ss,uint32_t tabs, bool tokencount) const {
1874
generateTabs(ss,tabs) << "<integer-difference>\n";
1875
for(auto& e : _exprs) e->toXML(ss,tabs+1);
1876
generateTabs(ss,tabs) << "</integer-difference>\n";
1879
void MultiplyExpr::toXML(std::ostream& ss,uint32_t tabs, bool tokencount) const {
1880
generateTabs(ss,tabs) << "<integer-product>\n";
1881
for(auto& e : _exprs) e->toXML(ss,tabs+1);
1882
generateTabs(ss,tabs) << "</integer-product>\n";
1885
void MinusExpr::toXML(std::ostream& out,uint32_t tabs, bool tokencount) const {
1887
generateTabs(out,tabs) << "<integer-product>\n";
1888
_expr->toXML(out,tabs+1);
1889
generateTabs(out,tabs+1) << "<integer-difference>\n" ; generateTabs(out,tabs+2) <<
1890
"<integer-constant>0</integer-constant>\n" ; generateTabs(out,tabs+2) <<
1891
"<integer-constant>1</integer-constant>\n" ; generateTabs(out,tabs+1) <<
1892
"</integer-difference>\n" ; generateTabs(out,tabs) << "</integer-product>\n";
1895
void EXCondition::toXML(std::ostream& out,uint32_t tabs) const {
1896
generateTabs(out,tabs) << "<exists-path>\n" ; generateTabs(out,tabs+1) << "<next>\n";
1897
_cond->toXML(out,tabs+2);
1898
generateTabs(out,tabs+1) << "</next>\n" ; generateTabs(out,tabs) << "</exists-path>\n";
1901
void AXCondition::toXML(std::ostream& out,uint32_t tabs) const {
1902
generateTabs(out,tabs) << "<all-paths>\n"; generateTabs(out,tabs+1) << "<next>\n";
1903
_cond->toXML(out,tabs+2);
1904
generateTabs(out,tabs+1) << "</next>\n"; generateTabs(out,tabs) << "</all-paths>\n";
1907
void EFCondition::toXML(std::ostream& out,uint32_t tabs) const {
1908
generateTabs(out,tabs) << "<exists-path>\n" ; generateTabs(out,tabs+1) << "<finally>\n";
1909
_cond->toXML(out,tabs+2);
1910
generateTabs(out,tabs+1) << "</finally>\n" ; generateTabs(out,tabs) << "</exists-path>\n";
1913
void AFCondition::toXML(std::ostream& out,uint32_t tabs) const {
1914
generateTabs(out,tabs) << "<all-paths>\n" ; generateTabs(out,tabs+1) << "<finally>\n";
1915
_cond->toXML(out,tabs+2);
1916
generateTabs(out,tabs+1) << "</finally>\n" ; generateTabs(out,tabs) << "</all-paths>\n";
1919
void EGCondition::toXML(std::ostream& out,uint32_t tabs) const {
1920
generateTabs(out,tabs) << "<exists-path>\n" ; generateTabs(out,tabs+1) << "<globally>\n";
1921
_cond->toXML(out,tabs+2);
1922
generateTabs(out,tabs+1) << "</globally>\n" ; generateTabs(out,tabs) << "</exists-path>\n";
1925
void AGCondition::toXML(std::ostream& out,uint32_t tabs) const {
1926
generateTabs(out,tabs) << "<all-paths>\n" ; generateTabs(out,tabs+1) << "<globally>\n";
1927
_cond->toXML(out,tabs+2);
1928
generateTabs(out,tabs+1) << "</globally>\n" ; generateTabs(out,tabs) << "</all-paths>\n";
1931
void EUCondition::toXML(std::ostream& out,uint32_t tabs) const {
1932
generateTabs(out,tabs) << "<exists-path>\n" ; generateTabs(out,tabs+1) << "<until>\n" ; generateTabs(out,tabs+2) << "<before>\n";
1933
_cond1->toXML(out,tabs+3);
1934
generateTabs(out,tabs+2) << "</before>\n" ; generateTabs(out,tabs+2) << "<reach>\n";
1935
_cond2->toXML(out,tabs+3);
1936
generateTabs(out,tabs+2) << "</reach>\n" ; generateTabs(out,tabs+1) << "</until>\n" ; generateTabs(out,tabs) << "</exists-path>\n";
1939
void AUCondition::toXML(std::ostream& out,uint32_t tabs) const {
1940
generateTabs(out,tabs) << "<all-paths>\n" ; generateTabs(out,tabs+1) << "<until>\n" ; generateTabs(out,tabs+2) << "<before>\n";
1941
_cond1->toXML(out,tabs+3);
1942
generateTabs(out,tabs+2) << "</before>\n" ; generateTabs(out,tabs+2) << "<reach>\n";
1943
_cond2->toXML(out,tabs+3);
1944
generateTabs(out,tabs+2) << "</reach>\n" ; generateTabs(out,tabs+1) << "</until>\n" ; generateTabs(out,tabs) << "</all-paths>\n";
1947
void AndCondition::toXML(std::ostream& out,uint32_t tabs) const {
1948
if(_conds.size() == 0)
1950
BooleanCondition::TRUE_CONSTANT->toXML(out, tabs);
1953
if(_conds.size() == 1)
1955
_conds[0]->toXML(out, tabs);
1958
generateTabs(out,tabs) << "<conjunction>\n";
1959
_conds[0]->toXML(out, tabs + 1);
1960
for(size_t i = 1; i < _conds.size(); ++i)
1962
if(i + 1 == _conds.size())
1964
_conds[i]->toXML(out, tabs + i + 1);
1968
generateTabs(out,tabs + i) << "<conjunction>\n";
1969
_conds[i]->toXML(out, tabs + i + 1);
1972
for(size_t i = _conds.size() - 1; i > 1; --i)
1974
generateTabs(out,tabs + i) << "</conjunction>\n";
1976
generateTabs(out,tabs) << "</conjunction>\n";
1979
void OrCondition::toXML(std::ostream& out,uint32_t tabs) const {
1980
if(_conds.size() == 0)
1982
BooleanCondition::FALSE_CONSTANT->toXML(out, tabs);
1985
if(_conds.size() == 1)
1987
_conds[0]->toXML(out, tabs);
1990
generateTabs(out,tabs) << "<disjunction>\n";
1991
_conds[0]->toXML(out, tabs + 1);
1992
for(size_t i = 1; i < _conds.size(); ++i)
1994
if(i + 1 == _conds.size())
1996
_conds[i]->toXML(out, tabs + i + 1);
2000
generateTabs(out,tabs + i) << "<disjunction>\n";
2001
_conds[i]->toXML(out, tabs + i + 1);
2004
for(size_t i = _conds.size() - 1; i > 1; --i)
2006
generateTabs(out,tabs + i) << "</disjunction>\n";
2008
generateTabs(out,tabs) << "</disjunction>\n";
2011
void CompareConjunction::toXML(std::ostream& out, uint32_t tabs) const
2013
if(_negated) generateTabs(out,tabs++) << "<negation>";
2014
if(_constraints.size() == 0) BooleanCondition::TRUE_CONSTANT->toXML(out, tabs);
2017
bool single = _constraints.size() == 1 &&
2018
(_constraints[0]._lower == 0 ||
2019
_constraints[0]._upper == std::numeric_limits<uint32_t>::max());
2021
generateTabs(out,tabs) << "<conjunction>\n";
2022
for(auto& c : _constraints)
2026
generateTabs(out,tabs+1) << "<integer-ge>\n";
2027
generateTabs(out,tabs+2) << "<tokens-count>\n";
2028
generateTabs(out,tabs+3) << "<place>" << c._name << "</place>\n";
2029
generateTabs(out,tabs+2) << "</tokens-count>\n";
2030
generateTabs(out,tabs+2) << "<integer-constant>" << c._lower << "</integer-constant>\n";
2031
generateTabs(out,tabs+1) << "</integer-ge>\n";
2033
if(c._upper != std::numeric_limits<uint32_t>::max())
2035
generateTabs(out,tabs+1) << "<integer-le>\n";
2036
generateTabs(out,tabs+2) << "<tokens-count>\n";
2037
generateTabs(out,tabs+3) << "<place>" << c._name << "</place>\n";
2038
generateTabs(out,tabs+2) << "</tokens-count>\n";
2039
generateTabs(out,tabs+2) << "<integer-constant>" << c._upper << "</integer-constant>\n";
2040
generateTabs(out,tabs+1) << "</integer-le>\n";
2044
generateTabs(out,tabs) << "</conjunction>\n";
2046
if(_negated) generateTabs(out,--tabs) << "</negation>";
2049
void EqualCondition::toXML(std::ostream& out,uint32_t tabs) const {
2050
generateTabs(out,tabs) << "<integer-eq>\n";
2051
_expr1->toXML(out,tabs+1);
2052
_expr2->toXML(out,tabs+1);
2053
generateTabs(out,tabs) << "</integer-eq>\n";
2056
void NotEqualCondition::toXML(std::ostream& out,uint32_t tabs) const {
2057
generateTabs(out,tabs) << "<integer-ne>\n";
2058
_expr1->toXML(out,tabs+1);
2059
_expr2->toXML(out,tabs+1);
2060
generateTabs(out,tabs) << "</integer-ne>\n";
2063
void LessThanCondition::toXML(std::ostream& out,uint32_t tabs) const {
2064
generateTabs(out,tabs) << "<integer-lt>\n";
2065
_expr1->toXML(out,tabs+1);
2066
_expr2->toXML(out,tabs+1);
2067
generateTabs(out,tabs) << "</integer-lt>\n";
2070
void LessThanOrEqualCondition::toXML(std::ostream& out,uint32_t tabs) const {
2071
generateTabs(out,tabs) << "<integer-le>\n";
2072
_expr1->toXML(out,tabs+1);
2073
_expr2->toXML(out,tabs+1);
2074
generateTabs(out,tabs) << "</integer-le>\n";
2077
void GreaterThanCondition::toXML(std::ostream& out,uint32_t tabs) const {
2078
generateTabs(out,tabs) << "<integer-gt>\n";
2079
_expr1->toXML(out,tabs+1);
2080
_expr2->toXML(out,tabs+1);
2081
generateTabs(out,tabs) << "</integer-gt>\n";
2084
void GreaterThanOrEqualCondition::toXML(std::ostream& out,uint32_t tabs) const {
2086
generateTabs(out,tabs) << "<integer-ge>\n";
2087
_expr1->toXML(out,tabs+1);
2088
_expr2->toXML(out,tabs+1);
2089
generateTabs(out,tabs) << "</integer-ge>\n";
2092
void NotCondition::toXML(std::ostream& out,uint32_t tabs) const {
2094
generateTabs(out,tabs) << "<negation>\n";
2095
_cond->toXML(out,tabs+1);
2096
generateTabs(out,tabs) << "</negation>\n";
2099
void BooleanCondition::toXML(std::ostream& out,uint32_t tabs) const {
2100
generateTabs(out,tabs) << "<" <<
2101
(_value ? "true" : "false")
2105
void DeadlockCondition::toXML(std::ostream& out,uint32_t tabs) const {
2106
generateTabs(out,tabs) << "<deadlock/>\n";
2109
void UnfoldedUpperBoundsCondition::toXML(std::ostream& out, uint32_t tabs) const {
2110
generateTabs(out, tabs) << "<place-bound>\n";
2111
for(auto& p : _places)
2112
generateTabs(out, tabs + 1) << "<place>" << p._name << "</place>\n";
2113
generateTabs(out, tabs) << "</place-bound>\n";
2116
/******************** Query Simplification ********************/
2118
Member LiteralExpr::constraint(SimplificationContext& context) const {
2119
return Member(_value);
2122
Member memberForPlace(size_t p, SimplificationContext& context)
2124
std::vector<int> row(context.net()->numberOfTransitions(), 0);
2125
row.shrink_to_fit();
2126
for (size_t t = 0; t < context.net()->numberOfTransitions(); t++) {
2127
row[t] = context.net()->outArc(t, p) - context.net()->inArc(p, t);
2129
return Member(std::move(row), context.marking()[p]);
2132
Member UnfoldedIdentifierExpr::constraint(SimplificationContext& context) const {
2133
return memberForPlace(_offsetInMarking, context);
2136
Member CommutativeExpr::commutativeCons(int constant, SimplificationContext& context, std::function<void(Member& a, Member b)> op) const
2140
if(_constant != constant || (_exprs.size() == 0 && _ids.size() == 0))
2143
res = Member(_constant);
2148
if(first) res = memberForPlace(i.first, context);
2149
else op(res, memberForPlace(i.first, context));
2153
for(auto& e : _exprs)
2155
if(first) res = e->constraint(context);
2156
else op(res, e->constraint(context));
2162
Member PlusExpr::constraint(SimplificationContext& context) const {
2163
return commutativeCons(0, context, [](auto& a , auto b){ a += b;});
2166
Member SubtractExpr::constraint(SimplificationContext& context) const {
2167
Member res = _exprs[0]->constraint(context);
2168
for(size_t i = 1; i < _exprs.size(); ++i) res -= _exprs[i]->constraint(context);
2172
Member MultiplyExpr::constraint(SimplificationContext& context) const {
2173
return commutativeCons(1, context, [](auto& a , auto b){ a *= b;});
2176
Member MinusExpr::constraint(SimplificationContext& context) const {
2178
return _expr->constraint(context) *= neg;
2181
Retval simplifyEX(Retval& r, SimplificationContext& context) {
2182
if(r.formula->isTriviallyTrue() || !r.neglps->satisfiable(context)) {
2183
return Retval(std::make_shared<NotCondition>(
2184
std::make_shared<DeadlockCondition>()));
2185
} else if(r.formula->isTriviallyFalse() || !r.lps->satisfiable(context)) {
2186
return Retval(BooleanCondition::FALSE_CONSTANT);
2188
return Retval(std::make_shared<EXCondition>(r.formula));
2192
Retval simplifyAX(Retval& r, SimplificationContext& context) {
2193
if(r.formula->isTriviallyTrue() || !r.neglps->satisfiable(context)){
2194
return Retval(BooleanCondition::TRUE_CONSTANT);
2195
} else if(r.formula->isTriviallyFalse() || !r.lps->satisfiable(context)){
2196
return Retval(std::make_shared<DeadlockCondition>());
2198
return Retval(std::make_shared<AXCondition>(r.formula));
2202
Retval simplifyEF(Retval& r, SimplificationContext& context){
2203
if(r.formula->isTriviallyTrue() || !r.neglps->satisfiable(context)){
2204
return Retval(BooleanCondition::TRUE_CONSTANT);
2205
} else if(r.formula->isTriviallyFalse() || !r.lps->satisfiable(context)){
2206
return Retval(BooleanCondition::FALSE_CONSTANT);
2208
return Retval(std::make_shared<EFCondition>(r.formula));
2212
Retval simplifyAF(Retval& r, SimplificationContext& context){
2213
if(r.formula->isTriviallyTrue() || !r.neglps->satisfiable(context)){
2214
return Retval(BooleanCondition::TRUE_CONSTANT);
2215
} else if(r.formula->isTriviallyFalse() || !r.lps->satisfiable(context)){
2216
return Retval(BooleanCondition::FALSE_CONSTANT);
2218
return Retval(std::make_shared<AFCondition>(r.formula));
2222
Retval simplifyEG(Retval& r, SimplificationContext& context){
2223
if(r.formula->isTriviallyTrue() || !r.neglps->satisfiable(context)){
2224
return Retval(BooleanCondition::TRUE_CONSTANT);
2225
} else if(r.formula->isTriviallyFalse() || !r.lps->satisfiable(context)){
2226
return Retval(BooleanCondition::FALSE_CONSTANT);
2228
return Retval(std::make_shared<EGCondition>(r.formula));
2232
Retval simplifyAG(Retval& r, SimplificationContext& context){
2233
if(r.formula->isTriviallyTrue() || !r.neglps->satisfiable(context)){
2234
return Retval(BooleanCondition::TRUE_CONSTANT);
2235
} else if(r.formula->isTriviallyFalse() || !r.lps->satisfiable(context)){
2236
return Retval(BooleanCondition::FALSE_CONSTANT);
2238
return Retval(std::make_shared<AGCondition>(r.formula));
2242
Retval EXCondition::simplify(SimplificationContext& context) const {
2243
Retval r = _cond->simplify(context);
2244
return context.negated() ? simplifyAX(r, context) : simplifyEX(r, context);
2247
Retval AXCondition::simplify(SimplificationContext& context) const {
2248
Retval r = _cond->simplify(context);
2249
return context.negated() ? simplifyEX(r, context) : simplifyAX(r, context);
2252
Retval EFCondition::simplify(SimplificationContext& context) const {
2253
Retval r = _cond->simplify(context);
2254
return context.negated() ? simplifyAG(r, context) : simplifyEF(r, context);
2257
Retval AFCondition::simplify(SimplificationContext& context) const {
2258
Retval r = _cond->simplify(context);
2259
return context.negated() ? simplifyEG(r, context) : simplifyAF(r, context);
2262
Retval EGCondition::simplify(SimplificationContext& context) const {
2263
Retval r = _cond->simplify(context);
2264
return context.negated() ? simplifyAF(r, context) : simplifyEG(r, context);
2267
Retval AGCondition::simplify(SimplificationContext& context) const {
2268
Retval r = _cond->simplify(context);
2269
return context.negated() ? simplifyEF(r, context) : simplifyAG(r, context);
2272
Retval EUCondition::simplify(SimplificationContext& context) const {
2273
// cannot push negation any further
2274
bool neg = context.negated();
2275
context.setNegate(false);
2276
Retval r2 = _cond2->simplify(context);
2277
if(r2.formula->isTriviallyTrue() || !r2.neglps->satisfiable(context))
2279
context.setNegate(neg);
2281
Retval(BooleanCondition::FALSE_CONSTANT) :
2282
Retval(BooleanCondition::TRUE_CONSTANT);
2284
else if(r2.formula->isTriviallyFalse() || !r2.lps->satisfiable(context))
2286
context.setNegate(neg);
2288
Retval(BooleanCondition::TRUE_CONSTANT) :
2289
Retval(BooleanCondition::FALSE_CONSTANT);
2291
Retval r1 = _cond1->simplify(context);
2292
context.setNegate(neg);
2294
if(context.negated()){
2295
if(r1.formula->isTriviallyTrue() || !r1.neglps->satisfiable(context)){
2296
return Retval(std::make_shared<NotCondition>(
2297
std::make_shared<EFCondition>(r2.formula)));
2298
} else if(r1.formula->isTriviallyFalse() || !r1.lps->satisfiable(context)){
2299
return Retval(std::make_shared<NotCondition>(r2.formula));
2301
return Retval(std::make_shared<NotCondition>(
2302
std::make_shared<EUCondition>(r1.formula, r2.formula)));
2305
if(r1.formula->isTriviallyTrue() || !r1.neglps->satisfiable(context)){
2306
return Retval(std::make_shared<EFCondition>(r2.formula));
2307
} else if(r1.formula->isTriviallyFalse() || !r1.lps->satisfiable(context)){
2310
return Retval(std::make_shared<EUCondition>(r1.formula, r2.formula));
2315
Retval AUCondition::simplify(SimplificationContext& context) const {
2316
// cannot push negation any further
2317
bool neg = context.negated();
2318
context.setNegate(false);
2319
Retval r2 = _cond2->simplify(context);
2320
if(r2.formula->isTriviallyTrue() || !r2.neglps->satisfiable(context))
2322
context.setNegate(neg);
2324
Retval(BooleanCondition::FALSE_CONSTANT) :
2325
Retval(BooleanCondition::TRUE_CONSTANT);
2327
else if(r2.formula->isTriviallyFalse() || !r2.lps->satisfiable(context))
2329
context.setNegate(neg);
2331
Retval(BooleanCondition::TRUE_CONSTANT) :
2332
Retval(BooleanCondition::FALSE_CONSTANT);
2334
Retval r1 = _cond1->simplify(context);
2335
context.setNegate(neg);
2337
if(context.negated()){
2338
if(r1.formula->isTriviallyTrue() || !r1.neglps->satisfiable(context)){
2339
return Retval(std::make_shared<NotCondition>(
2340
std::make_shared<AFCondition>(r2.formula)));
2341
} else if(r1.formula->isTriviallyFalse() || !r1.lps->satisfiable(context)){
2342
return Retval(std::make_shared<NotCondition>(r2.formula));
2344
return Retval(std::make_shared<NotCondition>(
2345
std::make_shared<AUCondition>(r1.formula, r2.formula)));
2348
if(r1.formula->isTriviallyTrue() || !r1.neglps->satisfiable(context)){
2349
return Retval(std::make_shared<AFCondition>(r2.formula));
2350
} else if(r1.formula->isTriviallyFalse() || !r1.lps->satisfiable(context)){
2353
return Retval(std::make_shared<AUCondition>(r1.formula, r2.formula));
2358
AbstractProgramCollection_ptr mergeLps(std::vector<AbstractProgramCollection_ptr>&& lps)
2360
if(lps.size() == 0) return nullptr;
2362
int i = lps.size() - 1;
2368
lps[j] = std::make_shared<MergeCollection>(lps[j], lps[i]);
2376
Retval LogicalCondition::simplifyAnd(SimplificationContext& context) const {
2378
std::vector<Condition_ptr> conditions;
2379
std::vector<AbstractProgramCollection_ptr> lpsv;
2380
std::vector<AbstractProgramCollection_ptr> neglps;
2381
for(auto& c : _conds)
2383
auto r = c->simplify(context);
2384
if(r.formula->isTriviallyFalse())
2386
return Retval(BooleanCondition::FALSE_CONSTANT);
2388
else if(r.formula->isTriviallyTrue())
2393
conditions.push_back(r.formula);
2394
lpsv.emplace_back(r.lps);
2395
neglps.emplace_back(r.neglps);
2398
if(conditions.size() == 0)
2400
return Retval(BooleanCondition::TRUE_CONSTANT);
2403
auto lps = mergeLps(std::move(lpsv));
2406
if(!context.timeout() && !lps->satisfiable(context))
2408
return Retval(BooleanCondition::FALSE_CONSTANT);
2411
catch(std::bad_alloc& e)
2413
// we are out of memory, deal with it.
2414
std::cout<<"Query reduction: memory exceeded during LPS merge."<<std::endl;
2417
// Lets try to see if the r1 AND r2 can ever be false at the same time
2418
// If not, then we know that r1 || r2 must be true.
2419
// we check this by checking if !r1 && !r2 is unsat
2422
makeAnd(conditions),
2424
std::make_shared<UnionCollection>(std::move(neglps)));
2427
Retval LogicalCondition::simplifyOr(SimplificationContext& context) const {
2429
std::vector<Condition_ptr> conditions;
2430
std::vector<AbstractProgramCollection_ptr> lps, neglpsv;
2431
for(auto& c : _conds)
2433
auto r = c->simplify(context);
2437
if(r.formula->isTriviallyTrue())
2439
return Retval(BooleanCondition::TRUE_CONSTANT);
2441
else if(r.formula->isTriviallyFalse())
2445
conditions.push_back(r.formula);
2446
lps.push_back(r.lps);
2447
neglpsv.emplace_back(r.neglps);
2450
AbstractProgramCollection_ptr neglps = mergeLps(std::move(neglpsv));
2452
if(conditions.size() == 0)
2454
return Retval(BooleanCondition::FALSE_CONSTANT);
2458
if(!context.timeout() && !neglps->satisfiable(context))
2460
return Retval(BooleanCondition::TRUE_CONSTANT);
2463
catch(std::bad_alloc& e)
2465
// we are out of memory, deal with it.
2466
std::cout<<"Query reduction: memory exceeded during LPS merge."<<std::endl;
2469
// Lets try to see if the r1 AND r2 can ever be false at the same time
2470
// If not, then we know that r1 || r2 must be true.
2471
// we check this by checking if !r1 && !r2 is unsat
2475
std::make_shared<UnionCollection>(std::move(lps)),
2479
Retval AndCondition::simplify(SimplificationContext& context) const {
2480
if(context.timeout())
2482
if(context.negated())
2483
return Retval(std::make_shared<NotCondition>(
2490
if(context.negated())
2491
return simplifyOr(context);
2493
return simplifyAnd(context);
2497
Retval OrCondition::simplify(SimplificationContext& context) const {
2498
if(context.timeout())
2500
if(context.negated())
2501
return Retval(std::make_shared<NotCondition>(
2504
return Retval(makeOr(_conds));
2506
if(context.negated())
2507
return simplifyAnd(context);
2509
return simplifyOr(context);
2512
Retval CompareConjunction::simplify(SimplificationContext& context) const {
2513
if(context.timeout())
2515
return Retval(std::make_shared<CompareConjunction>(*this, context.negated()));
2517
std::vector<AbstractProgramCollection_ptr> neglps, lpsv;
2518
auto neg = context.negated() != _negated;
2519
std::vector<cons_t> nconstraints;
2520
for(auto& c : _constraints)
2522
nconstraints.push_back(c);
2523
if(c._lower != 0 /*&& !context.timeout()*/ )
2525
auto m2 = memberForPlace(c._place, context);
2526
Member m1(c._lower);
2527
// test for trivial comparison
2528
Trivial eval = m1 <= m2;
2529
if(eval != Trivial::Indeterminate) {
2530
if(eval == Trivial::False)
2531
return Retval(BooleanCondition::getShared(neg));
2533
nconstraints.back()._lower = 0;
2534
} else { // if no trivial case
2535
int constant = m2.constant() - m1.constant();
2538
auto lp = std::make_shared<SingleProgram>(context.cache(), std::move(m1), constant, Simplification::OP_LE);
2539
auto nlp = std::make_shared<SingleProgram>(context.cache(), std::move(m2), constant, Simplification::OP_GT);
2541
neglps.push_back(nlp);
2545
if(c._upper != std::numeric_limits<uint32_t>::max() /*&& !context.timeout()*/)
2547
auto m1 = memberForPlace(c._place, context);
2548
Member m2(c._upper);
2549
// test for trivial comparison
2550
Trivial eval = m1 <= m2;
2551
if(eval != Trivial::Indeterminate) {
2552
if(eval == Trivial::False)
2553
return Retval(BooleanCondition::getShared(neg));
2555
nconstraints.back()._upper = std::numeric_limits<uint32_t>::max();
2556
} else { // if no trivial case
2557
int constant = m2.constant() - m1.constant();
2560
auto lp = std::make_shared<SingleProgram>(context.cache(), std::move(m1), constant, Simplification::OP_LE);
2561
auto nlp = std::make_shared<SingleProgram>(context.cache(), std::move(m2), constant, Simplification::OP_GT);
2563
neglps.push_back(nlp);
2567
assert(nconstraints.size() > 0);
2568
if(nconstraints.back()._lower == 0 && nconstraints.back()._upper == std::numeric_limits<uint32_t>::max())
2569
nconstraints.pop_back();
2571
assert(nconstraints.size() <= neglps.size()*2);
2574
auto lps = mergeLps(std::move(lpsv));
2576
if(lps == nullptr && !context.timeout())
2578
return Retval(BooleanCondition::getShared(!neg));
2582
if(!context.timeout() && lps && !lps->satisfiable(context))
2584
return Retval(BooleanCondition::getShared(neg));
2587
catch(std::bad_alloc& e)
2589
// we are out of memory, deal with it.
2590
std::cout<<"Query reduction: memory exceeded during LPS merge."<<std::endl;
2592
// Lets try to see if the r1 AND r2 can ever be false at the same time
2593
// If not, then we know that r1 || r2 must be true.
2594
// we check this by checking if !r1 && !r2 is unsat
2596
// remove trivial rules from neglp
2597
int ncnt = neglps.size() - 1;
2598
for(int i = nconstraints.size() - 1; i >= 0; --i)
2600
if(context.timeout()) break;
2603
auto& c = nconstraints[i];
2604
if(c._lower != 0) ++cnt;
2605
if(c._upper != std::numeric_limits<uint32_t>::max()) ++cnt;
2606
for(size_t j = 0; j < cnt ; ++j)
2609
if(!neglps[ncnt]->satisfiable(context))
2611
if(j == 1 || c._upper == std::numeric_limits<uint32_t>::max())
2614
c._upper = std::numeric_limits<uint32_t>::max();
2615
neglps.erase(neglps.begin() + ncnt);
2617
if(c._upper == std::numeric_limits<uint32_t>::max() && c._lower == 0)
2618
nconstraints.erase(nconstraints.begin() + i);
2623
catch(std::bad_alloc& e)
2625
// we are out of memory, deal with it.
2626
std::cout<<"Query reduction: memory exceeded during LPS merge."<<std::endl;
2628
if(nconstraints.size() == 0)
2630
return Retval(BooleanCondition::getShared(!neg));
2634
Condition_ptr rc = [&]() -> Condition_ptr {
2635
if(nconstraints.size() == 1)
2637
auto& c = nconstraints[0];
2638
auto id = std::make_shared<UnfoldedIdentifierExpr>(c._name, c._place);
2639
auto ll = std::make_shared<LiteralExpr>(c._lower);
2640
auto lu = std::make_shared<LiteralExpr>(c._upper);
2641
if(c._lower == c._upper)
2644
if(neg) return std::make_shared<NotEqualCondition>(id, lu);
2645
else return std::make_shared<EqualCondition>(id, lu);
2647
if(neg) return std::make_shared<GreaterThanCondition>(id, lu);
2648
else return std::make_shared<LessThanOrEqualCondition>(id, lu);
2652
if(c._lower != 0 && c._upper != std::numeric_limits<uint32_t>::max())
2654
if(neg) return makeOr(std::make_shared<LessThanCondition>(id, ll),std::make_shared<GreaterThanCondition>(id, lu));
2655
else return makeAnd(std::make_shared<GreaterThanOrEqualCondition>(id, ll),std::make_shared<LessThanOrEqualCondition>(id, lu));
2657
else if(c._lower != 0)
2659
if(neg) return std::make_shared<LessThanCondition>(id, ll);
2660
else return std::make_shared<GreaterThanOrEqualCondition>(id, ll);
2664
if(neg) return std::make_shared<GreaterThanCondition>(id, lu);
2665
else return std::make_shared<LessThanOrEqualCondition>(id, lu);
2671
return std::make_shared<CompareConjunction>(std::move(nconstraints), context.negated() != _negated);
2681
std::make_shared<UnionCollection>(std::move(neglps)));
2687
std::make_shared<UnionCollection>(std::move(neglps)),
2692
Retval EqualCondition::simplify(SimplificationContext& context) const {
2694
Member m1 = _expr1->constraint(context);
2695
Member m2 = _expr2->constraint(context);
2696
std::shared_ptr<AbstractProgramCollection> lps, neglps;
2697
if (!context.timeout() && m1.canAnalyze() && m2.canAnalyze()) {
2698
if ((m1.isZero() && m2.isZero()) || m1.substrationIsZero(m2)) {
2699
return Retval(BooleanCondition::getShared(
2700
context.negated() ? (m1.constant() != m2.constant()) : (m1.constant() == m2.constant())));
2702
int constant = m2.constant() - m1.constant();
2706
std::make_shared<UnionCollection>(
2707
std::make_shared<SingleProgram>(context.cache(), std::move(m1), constant, Simplification::OP_GT),
2708
std::make_shared<SingleProgram>(context.cache(), std::move(m2), constant, Simplification::OP_LT));
2710
lps = std::make_shared<SingleProgram>(context.cache(), std::move(m3), constant, Simplification::OP_EQ);
2712
if(context.negated()) lps.swap(neglps);
2715
lps = std::make_shared<SingleProgram>();
2716
neglps = std::make_shared<SingleProgram>();
2719
if (!context.timeout() && !lps->satisfiable(context)) {
2720
return Retval(BooleanCondition::FALSE_CONSTANT);
2722
else if(!context.timeout() && !neglps->satisfiable(context))
2724
return Retval(BooleanCondition::TRUE_CONSTANT);
2727
if (context.negated()) {
2728
return Retval(std::make_shared<NotEqualCondition>(_expr1, _expr2), std::move(lps), std::move(neglps));
2730
return Retval(std::make_shared<EqualCondition>(_expr1, _expr2), std::move(lps), std::move(neglps));
2735
Retval NotEqualCondition::simplify(SimplificationContext& context) const {
2736
Member m1 = _expr1->constraint(context);
2737
Member m2 = _expr2->constraint(context);
2738
std::shared_ptr<AbstractProgramCollection> lps, neglps;
2739
if (!context.timeout() && m1.canAnalyze() && m2.canAnalyze()) {
2740
if ((m1.isZero() && m2.isZero()) || m1.substrationIsZero(m2)) {
2741
return Retval(std::make_shared<BooleanCondition>(
2742
context.negated() ? (m1.constant() == m2.constant()) : (m1.constant() != m2.constant())));
2744
int constant = m2.constant() - m1.constant();
2748
std::make_shared<UnionCollection>(
2749
std::make_shared<SingleProgram>(context.cache(), std::move(m1), constant, Simplification::OP_GT),
2750
std::make_shared<SingleProgram>(context.cache(), std::move(m2), constant, Simplification::OP_LT));
2752
neglps = std::make_shared<SingleProgram>(context.cache(), std::move(m3), constant, Simplification::OP_EQ);
2754
if(context.negated()) lps.swap(neglps);
2757
lps = std::make_shared<SingleProgram>();
2758
neglps = std::make_shared<SingleProgram>();
2760
if (!context.timeout() && !lps->satisfiable(context)) {
2761
return Retval(BooleanCondition::FALSE_CONSTANT);
2763
else if(!context.timeout() && !neglps->satisfiable(context))
2765
return Retval(BooleanCondition::TRUE_CONSTANT);
2768
if (context.negated()) {
2769
return Retval(std::make_shared<EqualCondition>(_expr1, _expr2), std::move(lps), std::move(neglps));
2771
return Retval(std::make_shared<NotEqualCondition>(_expr1, _expr2), std::move(lps), std::move(neglps));
2776
Retval LessThanCondition::simplify(SimplificationContext& context) const {
2777
Member m1 = _expr1->constraint(context);
2778
Member m2 = _expr2->constraint(context);
2779
AbstractProgramCollection_ptr lps, neglps;
2780
if (!context.timeout() && m1.canAnalyze() && m2.canAnalyze()) {
2781
// test for trivial comparison
2782
Trivial eval = context.negated() ? m1 >= m2 : m1 < m2;
2783
if(eval != Trivial::Indeterminate) {
2784
return Retval(BooleanCondition::getShared(eval == Trivial::True));
2785
} else { // if no trivial case
2786
int constant = m2.constant() - m1.constant();
2789
lps = std::make_shared<SingleProgram>(context.cache(), std::move(m1), constant, (context.negated() ? Simplification::OP_GE : Simplification::OP_LT));
2790
neglps = std::make_shared<SingleProgram>(context.cache(), std::move(m2), constant, (!context.negated() ? Simplification::OP_GE : Simplification::OP_LT));
2793
lps = std::make_shared<SingleProgram>();
2794
neglps = std::make_shared<SingleProgram>();
2797
if (!context.timeout() && !lps->satisfiable(context)) {
2798
return Retval(BooleanCondition::FALSE_CONSTANT);
2800
else if(!context.timeout() && !neglps->satisfiable(context))
2802
return Retval(BooleanCondition::TRUE_CONSTANT);
2805
if (context.negated()) {
2806
return Retval(std::make_shared<GreaterThanOrEqualCondition>(_expr1, _expr2), std::move(lps), std::move(neglps));
2808
return Retval(std::make_shared<LessThanCondition>(_expr1, _expr2), std::move(lps), std::move(neglps));
2813
Retval LessThanOrEqualCondition::simplify(SimplificationContext& context) const {
2814
Member m1 = _expr1->constraint(context);
2815
Member m2 = _expr2->constraint(context);
2817
AbstractProgramCollection_ptr lps, neglps;
2818
if (!context.timeout() && m1.canAnalyze() && m2.canAnalyze()) {
2819
// test for trivial comparison
2820
Trivial eval = context.negated() ? m1 > m2 : m1 <= m2;
2821
if(eval != Trivial::Indeterminate) {
2822
return Retval(BooleanCondition::getShared(eval == Trivial::True));
2823
} else { // if no trivial case
2824
int constant = m2.constant() - m1.constant();
2827
lps = std::make_shared<SingleProgram>(context.cache(), std::move(m1), constant, (context.negated() ? Simplification::OP_GT : Simplification::OP_LE));
2828
neglps = std::make_shared<SingleProgram>(context.cache(), std::move(m2), constant, (context.negated() ? Simplification::OP_LE : Simplification::OP_GT));
2831
lps = std::make_shared<SingleProgram>();
2832
neglps = std::make_shared<SingleProgram>();
2838
if(!context.timeout() && !neglps->satisfiable(context)){
2839
return Retval(BooleanCondition::TRUE_CONSTANT);
2840
} else if (!context.timeout() && !lps->satisfiable(context)) {
2841
return Retval(BooleanCondition::FALSE_CONSTANT);
2843
if (context.negated()) {
2844
return Retval(std::make_shared<GreaterThanCondition>(_expr1, _expr2), std::move(lps), std::move(neglps));
2846
return Retval(std::make_shared<LessThanOrEqualCondition>(_expr1, _expr2),
2847
std::move(lps), std::move(neglps));
2852
Retval GreaterThanCondition::simplify(SimplificationContext& context) const {
2853
Member m1 = _expr1->constraint(context);
2854
Member m2 = _expr2->constraint(context);
2856
AbstractProgramCollection_ptr lps, neglps;
2857
if (!context.timeout() && m1.canAnalyze() && m2.canAnalyze()) {
2858
// test for trivial comparison
2859
Trivial eval = context.negated() ? m1 <= m2 : m1 > m2;
2860
if(eval != Trivial::Indeterminate) {
2861
return Retval(BooleanCondition::getShared(eval == Trivial::True));
2862
} else { // if no trivial case
2863
int constant = m2.constant() - m1.constant();
2866
lps = std::make_shared<SingleProgram>(context.cache(), std::move(m1), constant, (context.negated() ? Simplification::OP_LE : Simplification::OP_GT));
2867
neglps = std::make_shared<SingleProgram>(context.cache(), std::move(m2), constant, (context.negated() ? Simplification::OP_GT : Simplification::OP_LE));
2870
lps = std::make_shared<SingleProgram>();
2871
neglps = std::make_shared<SingleProgram>();
2874
if(!context.timeout() && !neglps->satisfiable(context)) {
2875
return Retval(BooleanCondition::TRUE_CONSTANT);
2876
}else if(!context.timeout() && !lps->satisfiable(context)) {
2877
return Retval(BooleanCondition::FALSE_CONSTANT);
2879
if (context.negated()) {
2880
return Retval(std::make_shared<LessThanOrEqualCondition>(_expr1, _expr2), std::move(lps), std::move(neglps));
2882
return Retval(std::make_shared<GreaterThanCondition>(_expr1, _expr2), std::move(lps), std::move(neglps));
2887
Retval GreaterThanOrEqualCondition::simplify(SimplificationContext& context) const {
2888
Member m1 = _expr1->constraint(context);
2889
Member m2 = _expr2->constraint(context);
2891
AbstractProgramCollection_ptr lps, neglps;
2892
if (!context.timeout() && m1.canAnalyze() && m2.canAnalyze()) {
2893
// test for trivial comparison
2894
Trivial eval = context.negated() ? m1 < m2 : m1 >= m2;
2895
if(eval != Trivial::Indeterminate) {
2896
return Retval(BooleanCondition::getShared(eval == Trivial::True));
2897
} else { // if no trivial case
2898
int constant = m2.constant() - m1.constant();
2901
lps = std::make_shared<SingleProgram>(context.cache(), std::move(m1), constant, (context.negated() ? Simplification::OP_LT : Simplification::OP_GE));
2902
neglps = std::make_shared<SingleProgram>(context.cache(), std::move(m2), constant, (!context.negated() ? Simplification::OP_LT : Simplification::OP_GE));
2905
lps = std::make_shared<SingleProgram>();
2906
neglps = std::make_shared<SingleProgram>();
2908
if (!context.timeout() && !lps->satisfiable(context))
2910
return Retval(BooleanCondition::FALSE_CONSTANT);
2912
else if(!context.timeout() && !neglps->satisfiable(context))
2914
return Retval(BooleanCondition::TRUE_CONSTANT);
2917
if (context.negated()) {
2918
return Retval(std::make_shared<LessThanCondition>(_expr1, _expr2), std::move(lps), std::move(neglps));
2920
return Retval(std::make_shared<GreaterThanOrEqualCondition>(_expr1, _expr2), std::move(lps), std::move(neglps));
2925
Retval NotCondition::simplify(SimplificationContext& context) const {
2927
Retval r = _cond->simplify(context);
2932
Retval BooleanCondition::simplify(SimplificationContext& context) const {
2933
if (context.negated()) {
2934
return Retval(getShared(!_value));
2936
return Retval(getShared(_value));
2940
Retval DeadlockCondition::simplify(SimplificationContext& context) const {
2941
if (context.negated()) {
2942
return Retval(std::make_shared<NotCondition>(DeadlockCondition::DEADLOCK));
2944
return Retval(DeadlockCondition::DEADLOCK);
2948
Retval UnfoldedUpperBoundsCondition::simplify(SimplificationContext& context) const
2950
std::vector<place_t> next;
2951
std::vector<uint32_t> places;
2952
for(auto& p : _places)
2953
places.push_back(p._place);
2954
const auto nplaces = _places.size();
2955
const auto bounds = LinearProgram::bounds(context, context.getLpTimeout(), places);
2956
double offset = _offset;
2957
for(size_t i = 0; i < nplaces; ++i)
2959
if(bounds[i].first != 0 && !bounds[i].second)
2960
next.emplace_back(_places[i], bounds[i].first);
2961
if(bounds[i].second)
2962
offset += bounds[i].first;
2964
if(bounds[nplaces].second)
2967
return Retval(std::make_shared<UnfoldedUpperBoundsCondition>(next, 0, bounds[nplaces].first + _offset));
2969
return Retval(std::make_shared<UnfoldedUpperBoundsCondition>(next, bounds[nplaces].first-offset, offset));
2972
/******************** Check if query is a reachability query ********************/
2974
bool EXCondition::isReachability(uint32_t depth) const {
2978
bool EGCondition::isReachability(uint32_t depth) const {
2982
bool EFCondition::isReachability(uint32_t depth) const {
2983
return depth > 0 ? false : _cond->isReachability(depth + 1);
2986
bool AXCondition::isReachability(uint32_t depth) const {
2990
bool AGCondition::isReachability(uint32_t depth) const {
2991
return depth > 0 ? false : _cond->isReachability(depth + 1);
2994
bool AFCondition::isReachability(uint32_t depth) const {
2998
bool UntilCondition::isReachability(uint32_t depth) const {
3002
bool LogicalCondition::isReachability(uint32_t depth) const {
3003
if(depth == 0) return false;
3004
bool reachability = true;
3005
for(auto& c : _conds)
3007
reachability = reachability && c->isReachability(depth + 1);
3008
if(!reachability) break;
3010
return reachability;
3013
bool CompareCondition::isReachability(uint32_t depth) const {
3017
bool NotCondition::isReachability(uint32_t depth) const {
3018
return _cond->isReachability(depth);
3021
bool BooleanCondition::isReachability(uint32_t depth) const {
3025
bool DeadlockCondition::isReachability(uint32_t depth) const {
3029
bool UnfoldedUpperBoundsCondition::isReachability(uint32_t depth) const {
3033
/******************** Prepare Reachability Queries ********************/
3035
Condition_ptr EXCondition::prepareForReachability(bool negated) const {
3039
Condition_ptr EGCondition::prepareForReachability(bool negated) const {
3043
Condition_ptr EFCondition::prepareForReachability(bool negated) const {
3044
_cond->setInvariant(negated);
3048
Condition_ptr AXCondition::prepareForReachability(bool negated) const {
3052
Condition_ptr AGCondition::prepareForReachability(bool negated) const {
3053
Condition_ptr cond = std::make_shared<NotCondition>(_cond);
3054
cond->setInvariant(!negated);
3058
Condition_ptr AFCondition::prepareForReachability(bool negated) const {
3062
Condition_ptr UntilCondition::prepareForReachability(bool negated) const {
3066
Condition_ptr LogicalCondition::prepareForReachability(bool negated) const {
3070
Condition_ptr CompareConjunction::prepareForReachability(bool negated) const {
3074
Condition_ptr CompareCondition::prepareForReachability(bool negated) const {
3078
Condition_ptr NotCondition::prepareForReachability(bool negated) const {
3079
return _cond->prepareForReachability(!negated);
3082
Condition_ptr BooleanCondition::prepareForReachability(bool negated) const {
3086
Condition_ptr DeadlockCondition::prepareForReachability(bool negated) const {
3090
Condition_ptr UnfoldedUpperBoundsCondition::prepareForReachability(bool negated) const {
3094
/******************** Prepare CTL Queries ********************/
3096
Condition_ptr EGCondition::pushNegation(negstat_t& stats, const EvaluationContext& context, bool nested, bool negated, bool initrw) {
3098
return AFCondition(std::make_shared<NotCondition>(_cond)).pushNegation(stats, context, nested, !negated, initrw);
3101
Condition_ptr AGCondition::pushNegation(negstat_t& stats, const EvaluationContext& context, bool nested, bool negated, bool initrw) {
3103
return EFCondition(std::make_shared<NotCondition>(_cond)).pushNegation(stats, context, nested, !negated, initrw);
3106
Condition_ptr EXCondition::pushNegation(negstat_t& stats, const EvaluationContext& context, bool nested, bool negated, bool initrw) {
3107
return initialMarkingRW([&]() -> Condition_ptr {
3108
auto a = _cond->pushNegation(stats, context, true, negated, initrw);
3112
return AXCondition(a).pushNegation(stats, context, nested, false, initrw);
3116
if(a == BooleanCondition::FALSE_CONSTANT)
3117
{ ++stats[3]; return a;}
3118
if(a == BooleanCondition::TRUE_CONSTANT)
3119
{ ++stats[4]; return std::make_shared<NotCondition>(DeadlockCondition::DEADLOCK); }
3120
a = std::make_shared<EXCondition>(a);
3123
}, stats, context, nested, negated, initrw);
3126
Condition_ptr AXCondition::pushNegation(negstat_t& stats, const EvaluationContext& context, bool nested, bool negated, bool initrw) {
3127
return initialMarkingRW([&]() -> Condition_ptr {
3128
auto a = _cond->pushNegation(stats, context, true, negated, initrw);
3132
return EXCondition(a).pushNegation(stats, context, nested, false, initrw);
3136
if(a == BooleanCondition::TRUE_CONSTANT)
3137
{ ++stats[6]; return a;}
3138
if(a == BooleanCondition::FALSE_CONSTANT)
3139
{ ++stats[7]; return DeadlockCondition::DEADLOCK; }
3140
a = std::make_shared<AXCondition>(a);
3143
}, stats, context, nested, negated, initrw);
3147
Condition_ptr EFCondition::pushNegation(negstat_t& stats, const EvaluationContext& context, bool nested, bool negated, bool initrw) {
3148
return initialMarkingRW([&]() -> Condition_ptr {
3149
auto a = _cond->pushNegation(stats, context, true, false, initrw);
3151
if(auto cond = dynamic_cast<NotCondition*>(a.get()))
3153
if((*cond)[0] == DeadlockCondition::DEADLOCK)
3156
return a->pushNegation(stats, context, nested, negated, initrw);
3160
if(!a->isTemporal())
3162
auto res = std::make_shared<EFCondition>(a);
3163
if(negated) return std::make_shared<NotCondition>(res);
3167
if( dynamic_cast<EFCondition*>(a.get()))
3170
if(negated) a = std::make_shared<NotCondition>(a);
3173
else if(auto cond = dynamic_cast<AFCondition*>(a.get()))
3176
a = EFCondition((*cond)[0]).pushNegation(stats, context, nested, negated, initrw);
3179
else if(auto cond = dynamic_cast<EUCondition*>(a.get()))
3182
a = EFCondition((*cond)[1]).pushNegation(stats, context, nested, negated, initrw);
3185
else if(auto cond = dynamic_cast<AUCondition*>(a.get()))
3188
a = EFCondition((*cond)[1]).pushNegation(stats, context, nested, negated, initrw);
3191
else if(auto cond = dynamic_cast<OrCondition*>(a.get()))
3193
if(!cond->isTemporal())
3195
Condition_ptr b = std::make_shared<EFCondition>(a);
3196
if(negated) b = std::make_shared<NotCondition>(b);
3200
std::vector<Condition_ptr> pef, atomic;
3201
for(auto& i : *cond)
3203
pef.push_back(std::make_shared<EFCondition>(i));
3205
a = makeOr(pef)->pushNegation(stats, context, nested, negated, initrw);
3210
Condition_ptr b = std::make_shared<EFCondition>(a);
3211
if(negated) b = std::make_shared<NotCondition>(b);
3214
}, stats, context, nested, negated, initrw);
3218
Condition_ptr AFCondition::pushNegation(negstat_t& stats, const EvaluationContext& context, bool nested, bool negated, bool initrw) {
3219
return initialMarkingRW([&]() -> Condition_ptr {
3220
auto a = _cond->pushNegation(stats, context, true, false, initrw);
3221
if(auto cond = dynamic_cast<NotCondition*>(a.get()))
3223
if((*cond)[0] == DeadlockCondition::DEADLOCK)
3226
return a->pushNegation(stats, context, nested, negated, initrw);
3230
if(dynamic_cast<AFCondition*>(a.get()))
3233
if(negated) return std::make_shared<NotCondition>(a);
3237
else if(dynamic_cast<EFCondition*>(a.get()))
3240
if(negated) return std::make_shared<NotCondition>(a);
3243
else if(auto cond = dynamic_cast<OrCondition*>(a.get()))
3246
std::vector<Condition_ptr> pef, npef;
3247
for(auto& i : *cond)
3249
if(dynamic_cast<EFCondition*>(i.get()))
3260
stats[17] += pef.size();
3261
pef.push_back(std::make_shared<AFCondition>(makeOr(npef)));
3262
return makeOr(pef)->pushNegation(stats, context, nested, negated, initrw);
3265
else if(auto cond = dynamic_cast<AUCondition*>(a.get()))
3268
return AFCondition((*cond)[1]).pushNegation(stats, context, nested, negated, initrw);
3270
auto b = std::make_shared<AFCondition>(a);
3271
if(negated) return std::make_shared<NotCondition>(b);
3273
}, stats, context, nested, negated, initrw);
3276
Condition_ptr AUCondition::pushNegation(negstat_t& stats, const EvaluationContext& context, bool nested, bool negated, bool initrw) {
3277
return initialMarkingRW([&]() -> Condition_ptr {
3278
auto b = _cond2->pushNegation(stats, context, true, false, initrw);
3279
auto a = _cond1->pushNegation(stats, context, true, false, initrw);
3280
if(auto cond = dynamic_cast<NotCondition*>(b.get()))
3282
if((*cond)[0] == DeadlockCondition::DEADLOCK)
3285
return b->pushNegation(stats, context, nested, negated, initrw);
3288
else if(a == DeadlockCondition::DEADLOCK)
3291
return b->pushNegation(stats, context, nested, negated, initrw);
3293
else if(auto cond = dynamic_cast<NotCondition*>(a.get()))
3295
if((*cond)[0] == DeadlockCondition::DEADLOCK)
3298
return AFCondition(b).pushNegation(stats, context, nested, negated, initrw);
3302
if(auto cond = dynamic_cast<AFCondition*>(b.get()))
3305
return cond->pushNegation(stats, context, nested, negated, initrw);
3307
else if(dynamic_cast<EFCondition*>(b.get()))
3310
if(negated) return std::make_shared<NotCondition>(b);
3313
else if(auto cond = dynamic_cast<OrCondition*>(b.get()))
3315
std::vector<Condition_ptr> pef, npef;
3316
for(auto& i : *cond)
3318
if(dynamic_cast<EFCondition*>(i.get()))
3329
stats[24] += pef.size();
3330
if(npef.size() != 0)
3332
pef.push_back(std::make_shared<AUCondition>(_cond1, makeOr(npef)));
3339
return makeOr(pef)->pushNegation(stats, context, nested, negated, initrw);
3343
auto c = std::make_shared<AUCondition>(a, b);
3344
if(negated) return std::make_shared<NotCondition>(c);
3346
}, stats, context, nested, negated, initrw);
3350
Condition_ptr EUCondition::pushNegation(negstat_t& stats, const EvaluationContext& context, bool nested, bool negated, bool initrw) {
3351
return initialMarkingRW([&]() -> Condition_ptr {
3352
auto b = _cond2->pushNegation(stats, context, true, false, initrw);
3353
auto a = _cond1->pushNegation(stats, context, true, false, initrw);
3355
if(auto cond = dynamic_cast<NotCondition*>(b.get()))
3357
if((*cond)[0] == DeadlockCondition::DEADLOCK)
3360
return b->pushNegation(stats, context, nested, negated, initrw);
3363
else if(a == DeadlockCondition::DEADLOCK)
3366
return b->pushNegation(stats, context, nested, negated, initrw);
3368
else if(auto cond = dynamic_cast<NotCondition*>(a.get()))
3370
if((*cond)[0] == DeadlockCondition::DEADLOCK)
3373
return EFCondition(b).pushNegation(stats, context, nested, negated, initrw);
3377
if(dynamic_cast<EFCondition*>(b.get()))
3380
if(negated) return std::make_shared<NotCondition>(b);
3383
else if(auto cond = dynamic_cast<OrCondition*>(b.get()))
3385
std::vector<Condition_ptr> pef, npef;
3386
for(auto& i : *cond)
3388
if(dynamic_cast<EFCondition*>(i.get()))
3399
stats[29] += pef.size();
3400
if(npef.size() != 0)
3402
pef.push_back(std::make_shared<EUCondition>(_cond1, makeOr(npef)));
3406
return makeOr(pef)->pushNegation(stats, context, nested, negated, initrw);
3409
auto c = std::make_shared<EUCondition>(a, b);
3410
if(negated) return std::make_shared<NotCondition>(c);
3412
}, stats, context, nested, negated, initrw);
3416
Condition_ptr pushAnd(const std::vector<Condition_ptr>& _conds, negstat_t& stats, const EvaluationContext& context, bool nested, bool negate_children, bool initrw)
3418
std::vector<Condition_ptr> nef, other;
3419
for(auto& c : _conds)
3421
auto n = c->pushNegation(stats, context, nested, negate_children, initrw);
3422
if(n->isTriviallyFalse()) return n;
3423
if(n->isTriviallyTrue()) continue;
3424
if(auto neg = dynamic_cast<NotCondition*>(n.get()))
3426
if(auto ef = dynamic_cast<EFCondition*>((*neg)[0].get()))
3428
nef.push_back((*ef)[0]);
3432
other.emplace_back(n);
3437
other.emplace_back(n);
3440
if(nef.size() + other.size() == 0) return BooleanCondition::TRUE_CONSTANT;
3441
if(nef.size() + other.size() == 1)
3443
return nef.size() == 0 ?
3445
std::make_shared<NotCondition>(std::make_shared<EFCondition>(nef[0]));
3447
if(nef.size() != 0) other.push_back(
3448
std::make_shared<NotCondition>(
3449
std::make_shared<EFCondition>(
3451
if(other.size() == 1) return other[0];
3452
auto res = makeAnd(other);
3456
Condition_ptr pushOr(const std::vector<Condition_ptr>& _conds, negstat_t& stats, const EvaluationContext& context, bool nested, bool negate_children, bool initrw)
3458
std::vector<Condition_ptr> nef, other;
3459
for(auto& c : _conds)
3461
auto n = c->pushNegation(stats, context, nested, negate_children, initrw);
3462
if(n->isTriviallyTrue())
3466
if(n->isTriviallyFalse()) continue;
3467
if(auto ef = dynamic_cast<EFCondition*>(n.get()))
3469
nef.push_back((*ef)[0]);
3473
other.emplace_back(n);
3476
if(nef.size() + other.size() == 0) return BooleanCondition::FALSE_CONSTANT;
3477
if(nef.size() + other.size() == 1) { return nef.size() == 0 ? other[0] : std::make_shared<EFCondition>(nef[0]);}
3478
if(nef.size() != 0) other.push_back(
3479
std::make_shared<EFCondition>(
3481
if(other.size() == 1) return other[0];
3482
return makeOr(other);
3485
Condition_ptr OrCondition::pushNegation(negstat_t& stats, const EvaluationContext& context, bool nested, bool negated, bool initrw) {
3486
return initialMarkingRW([&]() -> Condition_ptr {
3487
return negated ? pushAnd(_conds, stats, context, nested, true, initrw) :
3488
pushOr (_conds, stats, context, nested, false, initrw);
3489
}, stats, context, nested, negated, initrw);
3493
Condition_ptr AndCondition::pushNegation(negstat_t& stats, const EvaluationContext& context, bool nested, bool negated, bool initrw) {
3494
return initialMarkingRW([&]() -> Condition_ptr {
3495
return negated ? pushOr (_conds, stats, context, nested, true, initrw) :
3496
pushAnd(_conds, stats, context, nested, false, initrw);
3498
}, stats, context, nested, negated, initrw);
3501
Condition_ptr CompareConjunction::pushNegation(negstat_t& stats, const EvaluationContext& context, bool nested, bool negated, bool initrw) {
3502
return initialMarkingRW([&]() -> Condition_ptr {
3503
return std::make_shared<CompareConjunction>(*this, negated);
3504
}, stats, context, nested, negated, initrw);
3508
Condition_ptr NotCondition::pushNegation(negstat_t& stats, const EvaluationContext& context, bool nested, bool negated, bool initrw) {
3509
return initialMarkingRW([&]() -> Condition_ptr {
3510
if(negated) ++stats[30];
3511
return _cond->pushNegation(stats, context, nested, !negated, initrw);
3512
}, stats, context, nested, negated, initrw);
3515
template<typename T>
3516
Condition_ptr pushFireableNegation(negstat_t& stat, const EvaluationContext& context, bool nested, bool negated, bool initrw, const std::string& name, const Condition_ptr& compiled)
3519
return compiled->pushNegation(stat, context, nested, negated, initrw);
3522
stat.negated_fireability = true;
3523
return std::make_shared<NotCondition>(std::make_shared<T>(name));
3526
return std::make_shared<T>(name);
3529
Condition_ptr UnfoldedFireableCondition::pushNegation(negstat_t& stat, const EvaluationContext& context, bool nested, bool negated, bool initrw)
3531
return pushFireableNegation<UnfoldedFireableCondition>(stat, context, nested, negated, initrw, _name, _compiled);
3534
Condition_ptr FireableCondition::pushNegation(negstat_t& stat, const EvaluationContext& context, bool nested, bool negated, bool initrw)
3536
return pushFireableNegation<FireableCondition>(stat, context, nested, negated, initrw, _name, _compiled);
3539
bool CompareCondition::isTrivial() const
3541
auto remdup = [](auto& a, auto& b){
3542
auto ai = a->_ids.begin();
3543
auto bi = b->_ids.begin();
3544
while(ai != a->_ids.end() && bi != b->_ids.end())
3546
while(ai != a->_ids.end() && ai->first < bi->first) ++ai;
3547
if(ai == a->_ids.end()) break;
3548
if(ai->first == bi->first)
3550
ai = a->_ids.erase(ai);
3551
bi = b->_ids.erase(bi);
3557
if(bi == b->_ids.end() || ai == a->_ids.end()) break;
3560
if(auto p1 = dynamic_pointer_cast<PlusExpr>(_expr1))
3561
if(auto p2 = dynamic_pointer_cast<PlusExpr>(_expr2))
3564
if(auto m1 = dynamic_pointer_cast<MultiplyExpr>(_expr1))
3565
if(auto m2 = dynamic_pointer_cast<MultiplyExpr>(_expr2))
3568
if(auto p1 = dynamic_pointer_cast<CommutativeExpr>(_expr1))
3569
if(auto p2 = dynamic_pointer_cast<CommutativeExpr>(_expr2))
3570
return p1->_exprs.size() + p1->_ids.size() + p2->_exprs.size() + p2->_ids.size() == 0;
3571
return _expr1->placeFree() && _expr2->placeFree();
3574
Condition_ptr LessThanCondition::pushNegation(negstat_t& stats, const EvaluationContext& context, bool nested, bool negated, bool initrw) {
3575
return initialMarkingRW([&]() -> Condition_ptr {
3576
if(isTrivial()) return BooleanCondition::getShared(evaluate(context) xor negated);
3577
if(negated) return std::make_shared<GreaterThanOrEqualCondition>(_expr1, _expr2);
3578
else return std::make_shared<LessThanCondition>(_expr1, _expr2);
3579
}, stats, context, nested, negated, initrw);
3583
Condition_ptr GreaterThanOrEqualCondition::pushNegation(negstat_t& stats, const EvaluationContext& context, bool nested, bool negated, bool initrw) {
3584
return initialMarkingRW([&]() -> Condition_ptr {
3585
if(isTrivial()) return BooleanCondition::getShared(evaluate(context) xor negated);
3586
if(negated) return std::make_shared<LessThanCondition>(_expr1, _expr2);
3587
else return std::make_shared<GreaterThanOrEqualCondition>(_expr1, _expr2);
3588
}, stats, context, nested, negated, initrw);
3592
Condition_ptr LessThanOrEqualCondition::pushNegation(negstat_t& stats, const EvaluationContext& context, bool nested, bool negated, bool initrw) {
3593
return initialMarkingRW([&]() -> Condition_ptr {
3594
if(isTrivial()) return BooleanCondition::getShared(evaluate(context) xor negated);
3595
if(negated) return std::make_shared<GreaterThanCondition>(_expr1, _expr2);
3596
else return std::make_shared<LessThanOrEqualCondition>(_expr1, _expr2);
3597
}, stats, context, nested, negated, initrw);
3601
Condition_ptr GreaterThanCondition::pushNegation(negstat_t& stats, const EvaluationContext& context, bool nested, bool negated, bool initrw) {
3602
return initialMarkingRW([&]() -> Condition_ptr {
3603
if(isTrivial()) return BooleanCondition::getShared(evaluate(context) xor negated);
3604
if(negated) return std::make_shared<LessThanOrEqualCondition>(_expr1, _expr2);
3605
else return std::make_shared<GreaterThanCondition>(_expr1, _expr2);
3606
}, stats, context, nested, negated, initrw);
3609
Condition_ptr pushEqual(CompareCondition* org, bool negated, bool noteq, const EvaluationContext& context)
3611
if(org->isTrivial()) return BooleanCondition::getShared(org->evaluate(context) xor negated);
3614
if((*org)[i]->placeFree() && (*org)[i]->evaluate(context) == 0)
3616
if(negated == noteq) return std::make_shared<LessThanOrEqualCondition>((*org)[(i + 1) % 2], std::make_shared<LiteralExpr>(0));
3617
else return std::make_shared<GreaterThanOrEqualCondition>((*org)[(i + 1) % 2], std::make_shared<LiteralExpr>(1));
3620
if(negated == noteq) return std::make_shared<EqualCondition>((*org)[0], (*org)[1]);
3621
else return std::make_shared<NotEqualCondition>((*org)[0], (*org)[1]);
3624
Condition_ptr NotEqualCondition::pushNegation(negstat_t& stats, const EvaluationContext& context, bool nested, bool negated, bool initrw) {
3625
return initialMarkingRW([&]() -> Condition_ptr {
3626
return pushEqual(this, negated, true, context);
3627
}, stats, context, nested, negated, initrw);
3631
Condition_ptr EqualCondition::pushNegation(negstat_t& stats, const EvaluationContext& context, bool nested, bool negated, bool initrw) {
3632
return initialMarkingRW([&]() -> Condition_ptr {
3633
return pushEqual(this, negated, false, context);
3634
}, stats, context, nested, negated, initrw);
3637
Condition_ptr BooleanCondition::pushNegation(negstat_t& stats, const EvaluationContext& context, bool nested, bool negated, bool initrw) {
3638
return initialMarkingRW([&]() -> Condition_ptr {
3639
if(negated) return getShared(!_value);
3640
else return getShared( _value);
3641
}, stats, context, nested, negated, initrw);
3644
Condition_ptr DeadlockCondition::pushNegation(negstat_t& stats, const EvaluationContext& context, bool nested, bool negated, bool initrw) {
3645
return initialMarkingRW([&]() -> Condition_ptr {
3646
if(negated) return std::make_shared<NotCondition>(DEADLOCK);
3647
else return DEADLOCK;
3648
}, stats, context, nested, negated, initrw);
3651
Condition_ptr UnfoldedUpperBoundsCondition::pushNegation(negstat_t&, const EvaluationContext& context, bool nested, bool negated, bool initrw) {
3654
std::cerr << "UPPER BOUNDS CANNOT BE NEGATED!" << std::endl;
3657
return std::make_shared<UnfoldedUpperBoundsCondition>(_places, _max, _offset);
3661
/******************** Stubborn reduction interesting transitions ********************/
3663
void PlusExpr::incr(ReducingSuccessorGenerator& generator) const {
3664
for(auto& i : _ids) generator.presetOf(i.first, true);
3665
for(auto& e : _exprs) e->incr(generator);
3668
void PlusExpr::decr(ReducingSuccessorGenerator& generator) const {
3669
for(auto& i : _ids) generator.postsetOf(i.first, true);
3670
for(auto& e : _exprs) e->decr(generator);
3673
void SubtractExpr::incr(ReducingSuccessorGenerator& generator) const {
3675
for(auto& e : _exprs)
3685
void SubtractExpr::decr(ReducingSuccessorGenerator& generator) const {
3687
for(auto& e : _exprs)
3697
void MultiplyExpr::incr(ReducingSuccessorGenerator& generator) const {
3698
if((_ids.size() + _exprs.size()) == 1)
3700
for(auto& i : _ids) generator.presetOf(i.first, true);
3701
for(auto& e : _exprs) e->incr(generator);
3707
generator.presetOf(i.first, true);
3708
generator.postsetOf(i.first, true);
3710
for(auto& e : _exprs)
3718
void MultiplyExpr::decr(ReducingSuccessorGenerator& generator) const {
3719
if((_ids.size() + _exprs.size()) == 1)
3721
for(auto& i : _ids) generator.postsetOf(i.first, true);
3722
for(auto& e : _exprs) e->decr(generator);
3728
void MinusExpr::incr(ReducingSuccessorGenerator& generator) const {
3729
// TODO not implemented
3732
void MinusExpr::decr(ReducingSuccessorGenerator& generator) const {
3733
// TODO not implemented
3736
void LiteralExpr::incr(ReducingSuccessorGenerator& generator) const {
3740
void LiteralExpr::decr(ReducingSuccessorGenerator& generator) const {
3744
void UnfoldedIdentifierExpr::incr(ReducingSuccessorGenerator& generator) const {
3745
generator.presetOf(_offsetInMarking, true);
3748
void UnfoldedIdentifierExpr::decr(ReducingSuccessorGenerator& generator) const {
3749
generator.postsetOf(_offsetInMarking, true);
3752
void SimpleQuantifierCondition::findInteresting(ReducingSuccessorGenerator& generator, bool negated) const{
3753
_cond->findInteresting(generator, negated);
3756
void UntilCondition::findInteresting(ReducingSuccessorGenerator& generator, bool negated) const{
3757
_cond1->findInteresting(generator, negated);
3758
_cond1->findInteresting(generator, !negated);
3759
_cond2->findInteresting(generator, negated);
3762
void AndCondition::findInteresting(ReducingSuccessorGenerator& generator, bool negated) const {
3763
if(!negated){ // and
3764
for(auto& c : _conds)
3766
if(!c->isSatisfied())
3768
c->findInteresting(generator, negated);
3773
for(auto& c : _conds) c->findInteresting(generator, negated);
3777
void OrCondition::findInteresting(ReducingSuccessorGenerator& generator, bool negated) const {
3779
for(auto& c : _conds) c->findInteresting(generator, negated);
3781
for(auto& c : _conds)
3783
if(c->isSatisfied())
3785
c->findInteresting(generator, negated);
3792
void CompareConjunction::findInteresting(ReducingSuccessorGenerator& generator, bool negated) const{
3794
auto neg = negated != _negated;
3795
int32_t cand = std::numeric_limits<int32_t>::max();
3797
for(auto& c : _constraints)
3799
auto val = generator.parent()[c._place];
3800
if(c._lower == c._upper)
3804
if(val != c._lower) continue;
3805
generator.postsetOf(c._place, true);
3806
generator.presetOf(c._place, true);
3810
if(val == c._lower) continue;
3811
if(val > c._lower) {
3824
if(val < c._lower && c._lower != 0)
3831
if(val > c._upper && c._upper != std::numeric_limits<uint32_t>::max())
3840
if(val >= c._lower && c._lower != 0)
3842
generator.postsetOf(c._place, true);
3845
if(val <= c._upper && c._upper != std::numeric_limits<uint32_t>::max())
3847
generator.presetOf(c._place, true);
3851
if(cand != std::numeric_limits<int32_t>::max())
3853
if(pre && generator.seenPre(cand))
3855
else if(!pre && generator.seenPost(cand))
3859
if(cand != std::numeric_limits<int32_t>::max())
3863
generator.presetOf(cand, true);
3867
generator.postsetOf(cand, true);
3872
void EqualCondition::findInteresting(ReducingSuccessorGenerator& generator, bool negated) const {
3873
if(!negated){ // equal
3874
if(_expr1->getEval() == _expr2->getEval()) { return; }
3875
if(_expr1->getEval() > _expr2->getEval()){
3876
_expr1->decr(generator);
3877
_expr2->incr(generator);
3879
_expr1->incr(generator);
3880
_expr2->decr(generator);
3882
} else { // not equal
3883
if(_expr1->getEval() != _expr2->getEval()) { return; }
3884
_expr1->incr(generator);
3885
_expr1->decr(generator);
3886
_expr2->incr(generator);
3887
_expr2->decr(generator);
3891
void NotEqualCondition::findInteresting(ReducingSuccessorGenerator& generator, bool negated) const {
3892
if(!negated){ // not equal
3893
if(_expr1->getEval() != _expr2->getEval()) { return; }
3894
_expr1->incr(generator);
3895
_expr1->decr(generator);
3896
_expr2->incr(generator);
3897
_expr2->decr(generator);
3899
if(_expr1->getEval() == _expr2->getEval()) { return; }
3900
if(_expr1->getEval() > _expr2->getEval()){
3901
_expr1->decr(generator);
3902
_expr2->incr(generator);
3904
_expr1->incr(generator);
3905
_expr2->decr(generator);
3910
void LessThanCondition::findInteresting(ReducingSuccessorGenerator& generator, bool negated) const {
3911
if(!negated){ // less than
3912
if(_expr1->getEval() < _expr2->getEval()) { return; }
3913
_expr1->decr(generator);
3914
_expr2->incr(generator);
3915
} else { // greater than or equal
3916
if(_expr1->getEval() >= _expr2->getEval()) { return; }
3917
_expr1->incr(generator);
3918
_expr2->decr(generator);
3922
void LessThanOrEqualCondition::findInteresting(ReducingSuccessorGenerator& generator, bool negated) const {
3923
if(!negated){ // less than or equal
3924
if(_expr1->getEval() <= _expr2->getEval()) { return; }
3925
_expr1->decr(generator);
3926
_expr2->incr(generator);
3927
} else { // greater than
3928
if(_expr1->getEval() > _expr2->getEval()) { return; }
3929
_expr1->incr(generator);
3930
_expr2->decr(generator);
3934
void GreaterThanCondition::findInteresting(ReducingSuccessorGenerator& generator, bool negated) const {
3935
if(!negated){ // greater than
3936
if(_expr1->getEval() > _expr2->getEval()) { return; }
3937
_expr1->incr(generator);
3938
_expr2->decr(generator);
3939
} else { // less than or equal
3940
if(_expr1->getEval() <= _expr2->getEval()) { return; }
3941
_expr1->decr(generator);
3942
_expr2->incr(generator);
3946
void GreaterThanOrEqualCondition::findInteresting(ReducingSuccessorGenerator& generator, bool negated) const {
3947
if(!negated){ // greater than or equal
3948
if(_expr1->getEval() >= _expr2->getEval()) { return; }
3949
_expr1->incr(generator);
3950
_expr2->decr(generator);
3951
} else { // less than
3952
if(_expr1->getEval() < _expr2->getEval()) { return; }
3953
_expr1->decr(generator);
3954
_expr2->incr(generator);
3958
void NotCondition::findInteresting(ReducingSuccessorGenerator& generator, bool negated) const {
3959
_cond->findInteresting(generator, !negated);
3962
void BooleanCondition::findInteresting(ReducingSuccessorGenerator& generator, bool negated) const {
3966
void DeadlockCondition::findInteresting(ReducingSuccessorGenerator& generator, bool negated) const {
3968
generator.postPresetOf(generator.leastDependentEnabled(), true);
3969
} // else add nothing
3972
void UnfoldedUpperBoundsCondition::findInteresting(ReducingSuccessorGenerator& generator, bool negated) const {
3973
for(auto& p : _places)
3975
generator.presetOf(p._place);
3979
/********************** CONSTRUCTORS *********************************/
3981
template<typename T>
3982
void postMerge(std::vector<Condition_ptr>& conds) {
3983
std::sort(std::begin(conds), std::end(conds),
3984
[](auto& a, auto& b) {
3985
return a->isTemporal() < b->isTemporal();
3989
AndCondition::AndCondition(std::vector<Condition_ptr>&& conds) {
3990
for (auto& c : conds) tryMerge<AndCondition>(_conds, c);
3991
for (auto& c : _conds) _temporal = _temporal || c->isTemporal();
3992
for (auto& c : _conds) _loop_sensitive = _loop_sensitive || c->isLoopSensitive();
3993
postMerge<AndCondition>(_conds);
3996
AndCondition::AndCondition(const std::vector<Condition_ptr>& conds) {
3997
for (auto& c : conds) tryMerge<AndCondition>(_conds, c);
3998
for (auto& c : _conds) _temporal = _temporal || c->isTemporal();
3999
for (auto& c : _conds) _loop_sensitive = _loop_sensitive || c->isLoopSensitive();
4000
postMerge<AndCondition>(_conds);
4003
AndCondition::AndCondition(Condition_ptr left, Condition_ptr right) {
4004
tryMerge<AndCondition>(_conds, left);
4005
tryMerge<AndCondition>(_conds, right);
4006
for (auto& c : _conds) _temporal = _temporal || c->isTemporal();
4007
for (auto& c : _conds) _loop_sensitive = _loop_sensitive || c->isLoopSensitive();
4008
postMerge<AndCondition>(_conds);
4011
OrCondition::OrCondition(std::vector<Condition_ptr>&& conds) {
4012
for (auto& c : conds) tryMerge<OrCondition>(_conds, c);
4013
for (auto& c : _conds) _temporal = _temporal || c->isTemporal();
4014
for (auto& c : _conds) _loop_sensitive = _loop_sensitive || c->isLoopSensitive();
4015
postMerge<AndCondition>(_conds);
4018
OrCondition::OrCondition(const std::vector<Condition_ptr>& conds) {
4019
for (auto& c : conds) tryMerge<OrCondition>(_conds, c);
4020
for (auto& c : _conds) _temporal = _temporal || c->isTemporal();
4021
for (auto& c : _conds) _loop_sensitive = _loop_sensitive || c->isLoopSensitive();
4022
postMerge<AndCondition>(_conds);
4025
OrCondition::OrCondition(Condition_ptr left, Condition_ptr right) {
4026
tryMerge<OrCondition>(_conds, left);
4027
tryMerge<OrCondition>(_conds, right);
4028
for (auto& c : _conds) _temporal = _temporal || c->isTemporal();
4029
for (auto& c : _conds) _loop_sensitive = _loop_sensitive || c->isLoopSensitive();
4030
postMerge<AndCondition>(_conds);
4034
CompareConjunction::CompareConjunction(const std::vector<Condition_ptr>& conditions, bool negated)
4037
merge(conditions, negated);
4040
void CompareConjunction::merge(const CompareConjunction& other)
4042
auto neg = _negated != other._negated;
4043
if(neg && other._constraints.size() > 1)
4045
std::cerr << "MERGE OF CONJUNCT AND DISJUNCT NOT ALLOWED" << std::endl;
4049
auto il = _constraints.begin();
4050
for(auto c : other._constraints)
4055
if(c._upper == std::numeric_limits<uint32_t>::max() && c._lower == 0)
4059
else if (c._upper != std::numeric_limits<uint32_t>::max() && c._lower != 0 && neg)
4061
std::cerr << "MERGE OF CONJUNCT AND DISJUNCT NOT ALLOWED" << std::endl;
4066
il = std::lower_bound(_constraints.begin(), _constraints.end(), c);
4067
if(il == _constraints.end() || il->_place != c._place)
4069
il = _constraints.insert(il, c);
4073
il->_lower = std::max(il->_lower, c._lower);
4074
il->_upper = std::min(il->_upper, c._upper);
4079
void CompareConjunction::merge(const std::vector<Condition_ptr>& conditions, bool negated)
4081
for(auto& c : conditions)
4083
auto cmp = dynamic_cast<CompareCondition*>(c.get());
4085
auto id = dynamic_cast<UnfoldedIdentifierExpr*>((*cmp)[0].get());
4087
bool inverted = false;
4088
EvaluationContext context;
4091
id = dynamic_cast<UnfoldedIdentifierExpr*>((*cmp)[1].get());
4092
val = (*cmp)[0]->evaluate(context);
4097
val = (*cmp)[1]->evaluate(context);
4101
next._place = id->offset();
4103
if(dynamic_cast<LessThanOrEqualCondition*>(c.get()))
4104
if(inverted) next._lower = val;
4105
else next._upper = val;
4106
else if(dynamic_cast<LessThanCondition*>(c.get()))
4107
if(inverted) next._lower = val+1;
4108
else next._upper = val-1;
4109
else if(dynamic_cast<GreaterThanOrEqualCondition*>(c.get()))
4110
if(inverted) next._upper = val;
4111
else next._lower = val;
4112
else if(dynamic_cast<GreaterThanCondition*>(c.get()))
4113
if(inverted) next._upper = val-1;
4114
else next._lower = val+1;
4115
else if(dynamic_cast<EqualCondition*>(c.get()))
4121
else if(dynamic_cast<NotEqualCondition*>(c.get()))
4126
negated = false; // we already handled negation here!
4130
std::cerr << "UNKNOWN " << std::endl;
4137
auto lb = std::lower_bound(std::begin(_constraints), std::end(_constraints), next);
4138
if(lb == std::end(_constraints) || lb->_place != next._place)
4140
next._name = id->name();
4141
_constraints.insert(lb, next);
4145
assert(id->name().compare(lb->_name) == 0);
4146
lb->intersect(next);
4151
void CommutativeExpr::init(std::vector<Expr_ptr>&& exprs)
4153
for (auto& e : exprs) {
4156
EvaluationContext c;
4157
_constant = apply(_constant, e->evaluate(c));
4159
else if (auto id = dynamic_pointer_cast<PQL::UnfoldedIdentifierExpr>(e)) {
4160
_ids.emplace_back(id->offset(), id->name());
4162
else if(auto c = dynamic_pointer_cast<CommutativeExpr>(e))
4164
// we should move up plus/multiply here when possible;
4165
if(c->_ids.size() == 0 && c->_exprs.size() == 0)
4167
_constant = apply(_constant, c->_constant);
4171
_exprs.emplace_back(std::move(e));
4174
_exprs.emplace_back(std::move(e));
4179
PlusExpr::PlusExpr(std::vector<Expr_ptr>&& exprs, bool tk) : CommutativeExpr(0), tk(tk)
4181
init(std::move(exprs));
4184
MultiplyExpr::MultiplyExpr(std::vector<Expr_ptr>&& exprs) : CommutativeExpr(1)
4186
init(std::move(exprs));
4189
bool LogicalCondition::nestedDeadlock() const {
4190
for(auto& c : _conds)
4192
if(c->getQuantifier() == PQL::DEADLOCK ||
4193
c->nestedDeadlock() ||
4194
(c->getQuantifier() == PQL::NEG &&
4195
(*static_cast<NotCondition*>(c.get()))[0]->getQuantifier() == PQL::DEADLOCK