Merge lp:~verifypn-cpn/verifypn/query_rewrite_fix into lp:verifypn

Proposed by Peter Gjøl Jensen
Status: Merged
Approved by: Jiri Srba
Approved revision: 216
Merged at revision: 213
Proposed branch: lp:~verifypn-cpn/verifypn/query_rewrite_fix
Merge into: lp:verifypn
Diff against target: 370 lines (+123/-110)
3 files modified
PetriEngine/PQL/Contexts.h (+4/-2)
PetriEngine/PQL/Expressions.cpp (+91/-107)
PetriEngine/PQL/Expressions.h (+28/-1)
To merge this branch: bzr merge lp:~verifypn-cpn/verifypn/query_rewrite_fix
Reviewer Review Type Date Requested Status
Jiri Srba Approve
Review via email: mp+353797@code.launchpad.net

Commit message

Fixes wrong answer in CTLFireability from MCC2018 using
-x 2 ./SmallOperatingSystem-PT-MT8192DC4096/model.pnml ./SmallOperatingSystem-PT-MT8192DC4096/CTLFireability.xml

Is consistent on 2017 models and queries.

To post a comment you must log in.
Revision history for this message
Jiri Srba (srba) :
review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'PetriEngine/PQL/Contexts.h'
--- PetriEngine/PQL/Contexts.h 2018-03-09 18:37:07 +0000
+++ PetriEngine/PQL/Contexts.h 2018-08-27 14:34:51 +0000
@@ -144,6 +144,8 @@
144 _marking = marking;144 _marking = marking;
145 _net = net;145 _net = net;
146 }146 }
147
148 EvaluationContext() {};
147149
148 const MarkVal* marking() const {150 const MarkVal* marking() const {
149 return _marking;151 return _marking;
@@ -157,8 +159,8 @@
157 return _net;159 return _net;
158 }160 }
159 private:161 private:
160 const MarkVal* _marking;162 const MarkVal* _marking = nullptr;
161 const PetriNet* _net;163 const PetriNet* _net = nullptr;
162 };164 };
163165
164 /** Context for distance computation */166 /** Context for distance computation */
165167
=== modified file 'PetriEngine/PQL/Expressions.cpp'
--- PetriEngine/PQL/Expressions.cpp 2018-05-12 15:14:12 +0000
+++ PetriEngine/PQL/Expressions.cpp 2018-08-27 14:34:51 +0000
@@ -69,8 +69,8 @@
69 }69 }
70 else70 else
71 {71 {
72 if(! ((dynamic_cast<UnfoldedIdentifierExpr*>((*comp)[0].get()) && dynamic_cast<LiteralExpr*>((*comp)[1].get())) ||72 if(! ((dynamic_cast<UnfoldedIdentifierExpr*>((*comp)[0].get()) && (*comp)[1]->placeFree()) ||
73 (dynamic_cast<UnfoldedIdentifierExpr*>((*comp)[1].get()) && dynamic_cast<LiteralExpr*>((*comp)[0].get()))))73 (dynamic_cast<UnfoldedIdentifierExpr*>((*comp)[1].get()) && (*comp)[0]->placeFree())))
74 {74 {
75 _conds.emplace_back(ptr);75 _conds.emplace_back(ptr);
76 return;76 return;
@@ -807,8 +807,7 @@
807 context.marking()[c._place] >= c._lower;807 context.marking()[c._place] >= c._lower;
808 if(!res) break;808 if(!res) break;
809 }809 }
810 810 return (_negated xor res) ? RTRUE : RFALSE;
811 return _negated xor res ? RTRUE : RFALSE;
812 }811 }
813 812
814 Condition::Result CompareCondition::evaluate(const EvaluationContext& context) {813 Condition::Result CompareCondition::evaluate(const EvaluationContext& context) {
@@ -2486,8 +2485,15 @@
2486 auto id = std::make_shared<UnfoldedIdentifierExpr>(c._name, c._place);2485 auto id = std::make_shared<UnfoldedIdentifierExpr>(c._name, c._place);
2487 auto ll = std::make_shared<LiteralExpr>(c._lower);2486 auto ll = std::make_shared<LiteralExpr>(c._lower);
2488 auto lu = std::make_shared<LiteralExpr>(c._upper);2487 auto lu = std::make_shared<LiteralExpr>(c._upper);
2489 if (c._lower == c._upper && !neg) return std::make_shared<EqualCondition>(id, lu);2488 if(c._lower == c._upper)
2490 else if(c._lower == c._upper && neg) return std::make_shared<NotEqualCondition>(id, lu);2489 {
2490 if(c._lower != 0)
2491 if(neg) return std::make_shared<NotEqualCondition>(id, lu);
2492 else return std::make_shared<EqualCondition>(id, lu);
2493 else
2494 if(neg) return std::make_shared<GreaterThanCondition>(id, lu);
2495 else return std::make_shared<LessThanOrEqualCondition>(id, lu);
2496 }
2491 else2497 else
2492 {2498 {
2493 if(c._lower != 0 && c._upper != std::numeric_limits<uint32_t>::max())2499 if(c._lower != 0 && c._upper != std::numeric_limits<uint32_t>::max())
@@ -3480,20 +3486,33 @@
3480 }, stats, context, nested, negated, initrw);3486 }, stats, context, nested, negated, initrw);
3481 }3487 }
3482 3488
3489 Condition_ptr pushEqual(CompareCondition* org, bool negated, bool noteq, const EvaluationContext& context)
3490 {
3491 if(org->isTrivial()) return BooleanCondition::getShared(org->evaluate(context) xor negated);
3492 if((*org)[0]->placeFree() && (*org)[0]->evaluate(context) == 0)
3493 {
3494 if(negated == noteq) return std::make_shared<LessThanOrEqualCondition>((*org)[1], std::make_shared<LiteralExpr>(0));
3495 else return std::make_shared<GreaterThanOrEqualCondition>((*org)[1], std::make_shared<LiteralExpr>(1));
3496 }
3497 if((*org)[1]->placeFree() && (*org)[1]->evaluate(context) == 0)
3498 {
3499 if(negated == noteq) return std::make_shared<LessThanOrEqualCondition>((*org)[1], std::make_shared<LiteralExpr>(0));
3500 else return std::make_shared<GreaterThanOrEqualCondition>((*org)[1], std::make_shared<LiteralExpr>(1));
3501 }
3502 if(negated == noteq) return std::make_shared<EqualCondition>((*org)[0], (*org)[1]);
3503 else return std::make_shared<NotEqualCondition>((*org)[0], (*org)[1]);
3504 }
3505
3483 Condition_ptr NotEqualCondition::pushNegation(negstat_t& stats, const EvaluationContext& context, bool nested, bool negated, bool initrw) {3506 Condition_ptr NotEqualCondition::pushNegation(negstat_t& stats, const EvaluationContext& context, bool nested, bool negated, bool initrw) {
3484 return initialMarkingRW([&]() -> Condition_ptr {3507 return initialMarkingRW([&]() -> Condition_ptr {
3485 if(isTrivial()) return BooleanCondition::getShared(evaluate(context) xor negated);3508 return pushEqual(this, negated, true, context);
3486 if(negated) return std::make_shared<EqualCondition>(_expr1, _expr2);
3487 else return std::make_shared<NotEqualCondition>(_expr1, _expr2);
3488 }, stats, context, nested, negated, initrw);3509 }, stats, context, nested, negated, initrw);
3489 }3510 }
34903511
3491 3512
3492 Condition_ptr EqualCondition::pushNegation(negstat_t& stats, const EvaluationContext& context, bool nested, bool negated, bool initrw) {3513 Condition_ptr EqualCondition::pushNegation(negstat_t& stats, const EvaluationContext& context, bool nested, bool negated, bool initrw) {
3493 return initialMarkingRW([&]() -> Condition_ptr {3514 return initialMarkingRW([&]() -> Condition_ptr {
3494 if(isTrivial()) return BooleanCondition::getShared(evaluate(context) xor negated);3515 return pushEqual(this, negated, false, context);
3495 if(negated) return std::make_shared<NotEqualCondition>(_expr1, _expr2);
3496 else return std::make_shared<EqualCondition>(_expr1, _expr2);
3497 }, stats, context, nested, negated, initrw);3516 }, stats, context, nested, negated, initrw);
3498 }3517 }
3499 3518
@@ -3909,135 +3928,83 @@
3909 exit(ErrorCode);3928 exit(ErrorCode);
3910 }3929 }
3911 auto il = _constraints.begin();3930 auto il = _constraints.begin();
3912 for(auto& c : other._constraints)3931 for(auto c : other._constraints)
3913 {3932 {
3933 if(neg)
3934 c.invert();
3935
3936 if(c._upper == std::numeric_limits<uint32_t>::max() && c._lower == 0)
3937 {
3938 continue;
3939 }
3940 else if (c._upper != std::numeric_limits<uint32_t>::max() && c._lower != 0 && neg)
3941 {
3942 std::cerr << "MERGE OF CONJUNCT AND DISJUNCT NOT ALLOWED" << std::endl;
3943 assert(false);
3944 exit(ErrorCode);
3945 }
3946
3914 il = std::lower_bound(_constraints.begin(), _constraints.end(), c);3947 il = std::lower_bound(_constraints.begin(), _constraints.end(), c);
3915 cons_t c2;3948 if(il == _constraints.end() || il->_place != c._place)
3916 if(neg)3949 {
3917 {3950 il = _constraints.insert(il, c);
3918 if(c._upper == 0)3951 }
3919 {3952 else
3920 c2._lower = 1;3953 {
3921 }3954 il->_lower = std::max(il->_lower, c._lower);
3922 else if (c._upper == std::numeric_limits<uint32_t>::max())3955 il->_upper = std::min(il->_upper, c._upper);
3923 {
3924 c2._upper = c._lower + (other._negated ? -1 : 1);
3925 }
3926 else if(c._lower == 0)
3927 {
3928 c2._lower = c._upper + (other._negated ? 1 : -1);
3929 }
3930 else
3931 {
3932 std::cerr << "MERGE OF CONJUNCT AND DISJUNCT NOT ALLOWED" << std::endl;
3933 assert(false);
3934 exit(ErrorCode);
3935 }
3936 c2._place = c._place;
3937 assert(c2._lower <= c2._upper);
3938 }
3939 else
3940 {
3941 c2 = c;
3942 }
3943
3944 if(il == _constraints.end() || il->_place != c2._place)
3945 {
3946 c2._name = c._name;
3947 il = _constraints.insert(il, c2);
3948 }
3949 else
3950 {
3951 il->_lower = std::max(il->_lower, c2._lower);
3952 il->_upper = std::min(il->_upper, c2._upper);
3953 }3956 }
3954 }3957 }
3955 }3958 }
3956 3959
3957 void CompareConjunction::merge(const std::vector<Condition_ptr>& conditions, bool negated)3960 void CompareConjunction::merge(const std::vector<Condition_ptr>& conditions, bool negated)
3958 {3961 {
3959
3960 for(auto& c : conditions)3962 for(auto& c : conditions)
3961 {3963 {
3962 auto cmp = dynamic_cast<CompareCondition*>(c.get());3964 auto cmp = dynamic_cast<CompareCondition*>(c.get());
3963 assert(cmp);3965 assert(cmp);
3964 auto id = dynamic_cast<UnfoldedIdentifierExpr*>((*cmp)[0].get());3966 auto id = dynamic_cast<UnfoldedIdentifierExpr*>((*cmp)[0].get());
3965 LiteralExpr* lit = nullptr;3967 uint32_t val;
3966 bool inverted = false;3968 bool inverted = false;
3969 EvaluationContext context;
3967 if(!id)3970 if(!id)
3968 {3971 {
3969 id = dynamic_cast<UnfoldedIdentifierExpr*>((*cmp)[1].get());3972 id = dynamic_cast<UnfoldedIdentifierExpr*>((*cmp)[1].get());
3970 lit = dynamic_cast<LiteralExpr*>((*cmp)[0].get());3973 val = (*cmp)[0]->evaluate(context);
3971 inverted = true;3974 inverted = true;
3972 }3975 }
3973 else3976 else
3974 {3977 {
3975 lit = dynamic_cast<LiteralExpr*>((*cmp)[1].get()); 3978 val = (*cmp)[1]->evaluate(context);
3976 }3979 }
3977 assert(lit);
3978 assert(id);3980 assert(id);
3979 uint32_t val = lit->value();
3980 cons_t next;3981 cons_t next;
3981 next._place = id->offset();3982 next._place = id->offset();
3982 auto lb = std::lower_bound(std::begin(_constraints), std::end(_constraints), next);
3983 if(lb == std::end(_constraints))
3984 {
3985 next._name = id->name();
3986 lb = _constraints.insert(lb, next);
3987 }
3988 else
3989 {
3990 assert(id->name().compare(lb->_name) == 0);
3991 }
39923983
3993 if(dynamic_cast<LessThanOrEqualCondition*>(c.get()))3984 if(dynamic_cast<LessThanOrEqualCondition*>(c.get()))
3994 {3985 if(inverted) next._lower = val;
3995 if(!negated)3986 else next._upper = val;
3996 if(inverted) lb->_lower = std::max(lb->_lower, val);3987 else if(dynamic_cast<LessThanCondition*>(c.get()))
3997 else lb->_upper = std::min(lb->_upper, val);3988 if(inverted) next._lower = val+1;
3998 else3989 else next._upper = val-1;
3999 if(!inverted) lb->_lower = std::max(lb->_lower, val+1);
4000 else lb->_upper = std::min(lb->_upper, val-1);
4001 }
4002 else if(dynamic_cast<GreaterThanOrEqualCondition*>(c.get()))3990 else if(dynamic_cast<GreaterThanOrEqualCondition*>(c.get()))
4003 {3991 if(inverted) next._upper = val;
4004 if(!negated)3992 else next._lower = val;
4005 if(!inverted) lb->_lower = std::max(lb->_lower, val);
4006 else lb->_upper = std::min(lb->_upper, val);
4007 else
4008 if(inverted) lb->_lower = std::max(lb->_lower, val+1);
4009 else lb->_upper = std::min(lb->_upper, val-1);
4010 }
4011 else if(dynamic_cast<LessThanCondition*>(c.get()))
4012 {
4013 if(!negated)
4014 if(inverted) lb->_lower = std::max(lb->_lower, val+1);
4015 else lb->_upper = std::min(lb->_upper, val-1);
4016 else
4017 if(!inverted) lb->_lower = std::max(lb->_lower, val);
4018 else lb->_upper = std::min(lb->_upper, val);
4019
4020 }
4021 else if(dynamic_cast<GreaterThanCondition*>(c.get()))3993 else if(dynamic_cast<GreaterThanCondition*>(c.get()))
4022 {3994 if(inverted) next._upper = val-1;
4023 if(!negated)3995 else next._lower = val+1;
4024 if(!inverted) lb->_lower = std::max(lb->_lower, val+1);
4025 else lb->_upper = std::min(lb->_upper, val-1);
4026 else
4027 if(inverted) lb->_lower = std::max(lb->_lower, val);
4028 else lb->_upper = std::min(lb->_upper, val);
4029 }
4030 else if(dynamic_cast<EqualCondition*>(c.get()))3996 else if(dynamic_cast<EqualCondition*>(c.get()))
4031 {3997 {
4032 assert(!negated);3998 assert(!negated);
4033 lb->_lower = std::max(lb->_lower, val);3999 next._lower = val;
4034 lb->_upper = std::min(lb->_upper, val);4000 next._upper = val;
4035 }4001 }
4036 else if(dynamic_cast<NotEqualCondition*>(c.get()))4002 else if(dynamic_cast<NotEqualCondition*>(c.get()))
4037 {4003 {
4038 assert(negated);4004 assert(negated);
4039 lb->_lower = std::max(lb->_lower, val);4005 next._lower = val;
4040 lb->_upper = std::min(lb->_upper, val);4006 next._upper = val;
4007 negated = false; // we already handled negation here!
4041 }4008 }
4042 else4009 else
4043 {4010 {
@@ -4045,14 +4012,31 @@
4045 assert(false);4012 assert(false);
4046 exit(ErrorCode);4013 exit(ErrorCode);
4047 }4014 }
4015 if(negated)
4016 next.invert();
4017
4018 auto lb = std::lower_bound(std::begin(_constraints), std::end(_constraints), next);
4019 if(lb == std::end(_constraints) || lb->_place != next._place)
4020 {
4021 next._name = id->name();
4022 _constraints.insert(lb, next);
4023 }
4024 else
4025 {
4026 assert(id->name().compare(lb->_name) == 0);
4027 lb->intersect(next);
4028 }
4048 } 4029 }
4049 }4030 }
4050 4031
4051 void CommutativeExpr::init(std::vector<Expr_ptr>&& exprs)4032 void CommutativeExpr::init(std::vector<Expr_ptr>&& exprs)
4052 {4033 {
4053 for (auto& e : exprs) {4034 for (auto& e : exprs) {
4054 if (auto lit = dynamic_pointer_cast<PQL::LiteralExpr>(e))4035 if (e->placeFree())
4055 _constant = apply(_constant, lit->value());4036 {
4037 EvaluationContext c;
4038 _constant = apply(_constant, e->evaluate(c));
4039 }
4056 else if (auto id = dynamic_pointer_cast<PQL::UnfoldedIdentifierExpr>(e)) {4040 else if (auto id = dynamic_pointer_cast<PQL::UnfoldedIdentifierExpr>(e)) {
4057 _ids.emplace_back(id->offset(), id->name());4041 _ids.emplace_back(id->offset(), id->name());
4058 } 4042 }
40594043
=== modified file 'PetriEngine/PQL/Expressions.h'
--- PetriEngine/PQL/Expressions.h 2018-04-29 07:58:51 +0000
+++ PetriEngine/PQL/Expressions.h 2018-08-27 14:34:51 +0000
@@ -791,6 +791,33 @@
791 {791 {
792 return _place < other._place;792 return _place < other._place;
793 }793 }
794
795 void invert()
796 {
797 if(_lower == 0 && _upper == std::numeric_limits<uint32_t>::max())
798 return;
799 assert(_lower == 0 || _upper == std::numeric_limits<uint32_t>::max());
800 if(_lower == 0)
801 {
802 _lower = _upper + 1;
803 _upper = std::numeric_limits<uint32_t>::max();
804 }
805 else if(_upper == std::numeric_limits<uint32_t>::max())
806 {
807 _upper = _lower - 1;
808 _lower = 0;
809 }
810 else
811 {
812 assert(false);
813 }
814 }
815
816 void intersect(const cons_t& other)
817 {
818 _lower = std::max(_lower, other._lower);
819 _upper = std::min(_upper, other._upper);
820 }
794 };821 };
795822
796 CompareConjunction(bool negated = false) 823 CompareConjunction(bool negated = false)
@@ -884,13 +911,13 @@
884 }911 }
885 bool containsNext() const override { return false; }912 bool containsNext() const override { return false; }
886 bool nestedDeadlock() const override { return false; }913 bool nestedDeadlock() const override { return false; }
914 bool isTrivial() const;
887 protected:915 protected:
888 uint32_t _distance(DistanceContext& c, 916 uint32_t _distance(DistanceContext& c,
889 std::function<uint32_t(uint32_t, uint32_t, bool)> d) const917 std::function<uint32_t(uint32_t, uint32_t, bool)> d) const
890 {918 {
891 return d(_expr1->evaluate(c), _expr2->evaluate(c), c.negated());919 return d(_expr1->evaluate(c), _expr2->evaluate(c), c.negated());
892 }920 }
893 bool isTrivial() const;
894 private:921 private:
895 virtual bool apply(int v1, int v2) const = 0;922 virtual bool apply(int v1, int v2) const = 0;
896 virtual std::string op() const = 0;923 virtual std::string op() const = 0;

Subscribers

People subscribed via source and target branches