Merge lp:~tapaal-ltl/verifypn/ruleI.5 into lp:~tapaal-ltl/verifypn/ltl-model-checker

Proposed by Simon Virenfeldt
Status: Merged
Merged at revision: 252
Proposed branch: lp:~tapaal-ltl/verifypn/ruleI.5
Merge into: lp:~tapaal-ltl/verifypn/ltl-model-checker
Diff against target: 375 lines (+171/-122)
3 files modified
include/PetriEngine/Reducer.h (+8/-3)
src/PetriEngine/Reducer.cpp (+162/-118)
src/VerifyPN.cpp (+1/-1)
To merge this branch: bzr merge lp:~tapaal-ltl/verifypn/ruleI.5
Reviewer Review Type Date Requested Status
Nikolaj Jensen Ulrik Approve
Review via email: mp+398248@code.launchpad.net

Description of the change

Implements the new structural reduction rule K which is a weaker version of rule I tailored to LTL reduction.

To post a comment you must log in.
Revision history for this message
Nikolaj Jensen Ulrik (waefwerf) :
review: Approve
lp:~tapaal-ltl/verifypn/ruleI.5 updated
252. By Simon Virenfeldt

Merge lp:~tapaal-ltl/verifypn/ruleI.5@253

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'include/PetriEngine/Reducer.h'
--- include/PetriEngine/Reducer.h 2020-11-26 10:36:20 +0000
+++ include/PetriEngine/Reducer.h 2021-02-18 12:06:25 +0000
@@ -110,7 +110,8 @@
110 << "Applications of rule G: " << _ruleG << "\n"110 << "Applications of rule G: " << _ruleG << "\n"
111 << "Applications of rule H: " << _ruleH << "\n"111 << "Applications of rule H: " << _ruleH << "\n"
112 << "Applications of rule I: " << _ruleI << "\n"112 << "Applications of rule I: " << _ruleI << "\n"
113 << "Applications of rule J: " << _ruleJ << std::endl;113 << "Applications of rule J: " << _ruleJ << "\n"
114 << "Applications of rule K: " << _ruleK << std::endl;
114 }115 }
115116
116 void postFire(std::ostream&, const std::string& transition);117 void postFire(std::ostream&, const std::string& transition);
@@ -120,7 +121,7 @@
120 private:121 private:
121 size_t _removedTransitions = 0;122 size_t _removedTransitions = 0;
122 size_t _removedPlaces= 0;123 size_t _removedPlaces= 0;
123 size_t _ruleA = 0, _ruleB = 0, _ruleC = 0, _ruleD = 0, _ruleE = 0, _ruleF = 0, _ruleG = 0, _ruleH = 0, _ruleI = 0, _ruleJ = 0;124 size_t _ruleA = 0, _ruleB = 0, _ruleC = 0, _ruleD = 0, _ruleE = 0, _ruleF = 0, _ruleG = 0, _ruleH = 0, _ruleI = 0, _ruleJ = 0, _ruleK = 0;
124 PetriNetBuilder* parent = nullptr;125 PetriNetBuilder* parent = nullptr;
125 bool reconstructTrace = false;126 bool reconstructTrace = false;
126 std::chrono::high_resolution_clock::time_point _timer;127 std::chrono::high_resolution_clock::time_point _timer;
@@ -137,7 +138,11 @@
137 bool ReducebyRuleG(uint32_t* placeInQuery, bool remove_loops, bool remove_consumers);138 bool ReducebyRuleG(uint32_t* placeInQuery, bool remove_loops, bool remove_consumers);
138 bool ReducebyRuleH(uint32_t* placeInQuery);139 bool ReducebyRuleH(uint32_t* placeInQuery);
139 bool ReducebyRuleJ(uint32_t* placeInQuery);140 bool ReducebyRuleJ(uint32_t* placeInQuery);
140 141 bool ReducebyRuleK(uint32_t* placeInQuery, bool remove_consumers);
142
143 std::optional<std::pair<std::vector<bool>, std::vector<bool>>>relevant(const uint32_t* placeInQuery, bool remove_consumers);
144 bool remove_irrelevant(const uint32_t* placeInQuery, const std::vector<bool> &tseen, const std::vector<bool> &pseen);
145
141 std::string getTransitionName(uint32_t transition);146 std::string getTransitionName(uint32_t transition);
142 std::string getPlaceName(uint32_t place);147 std::string getPlaceName(uint32_t place);
143 148
144149
=== modified file 'src/PetriEngine/Reducer.cpp'
--- src/PetriEngine/Reducer.cpp 2020-12-04 11:14:38 +0000
+++ src/PetriEngine/Reducer.cpp 2021-02-18 12:06:25 +0000
@@ -903,131 +903,24 @@
903903
904 if(skipplace)904 if(skipplace)
905 skipPlace(p);905 skipPlace(p);
906 906
907 }907 }
908 assert(consistent());908 assert(consistent());
909 return continueReductions;909 return continueReductions;
910 }910 }
911 911
912 bool Reducer::ReducebyRuleI(uint32_t* placeInQuery, bool remove_loops, bool remove_consumers) {912 bool Reducer::ReducebyRuleI(uint32_t* placeInQuery, bool remove_loops, bool remove_consumers) {
913 bool reduced = false;913 bool reduced = false;
914 if(remove_loops)914 if(remove_loops)
915 {915 {
916 std::vector<uint32_t> wtrans;916
917 std::vector<bool> tseen(parent->numberOfTransitions(), false);917 auto result = relevant(placeInQuery, remove_consumers);
918918 if (!result) {
919 for(uint32_t p = 0; p < parent->numberOfPlaces(); ++p)919 return false;
920 {920 }
921 if(hasTimedout()) return false;921 auto[tseen, pseen] = result.value();
922 if(placeInQuery[p] > 0)922
923 {923 reduced |= remove_irrelevant(placeInQuery, tseen, pseen);
924 const Place& place = parent->_places[p];
925 for(auto t : place.consumers)
926 {
927 if(!tseen[t])
928 {
929 wtrans.push_back(t);
930 tseen[t] = true;
931 }
932 }
933 for(auto t : place.producers)
934 {
935 if(!tseen[t])
936 {
937 wtrans.push_back(t);
938 tseen[t] = true;
939 }
940 }
941 }
942 }
943
944 std::vector<bool> pseen(parent->numberOfPlaces(), false);
945 while(!wtrans.empty())
946 {
947 if(hasTimedout()) return false;
948 auto t = wtrans.back();
949 wtrans.pop_back();
950 const Transition& trans = parent->_transitions[t];
951 for(const Arc& arc : trans.pre)
952 {
953 const Place& place = parent->_places[arc.place];
954 if(arc.inhib)
955 {
956 for(auto pt : place.consumers)
957 {
958 if(!tseen[pt])
959 {
960 Transition& trans = parent->_transitions[pt];
961 auto it = trans.post.begin();
962 for(; it != trans.post.end(); ++it)
963 if(it->place >= arc.place) break;
964 if(it != trans.post.end() && it->place == arc.place)
965 {
966 auto it2 = trans.pre.begin();
967 for(; it2 != trans.pre.end(); ++it2)
968 if(it2->place >= arc.place || it2->inhib) break;
969 if(it->weight <= it2->weight) continue;
970 }
971 tseen[pt] = true;
972 wtrans.push_back(pt);
973 }
974 }
975 }
976 else
977 {
978 for(auto pt : place.producers)
979 {
980 if(!tseen[pt])
981 {
982 Transition& trans = parent->_transitions[pt];
983 auto it = trans.pre.begin();
984 for(; it != trans.pre.end(); ++it)
985 if(it->place >= arc.place) break;
986
987 if(it != trans.pre.end() && it->place == arc.place && !it->inhib)
988 {
989 auto it2 = trans.post.begin();
990 for(; it2 != trans.post.end(); ++it2)
991 if(it2->place >= arc.place) break;
992 if(it->weight >= it2->weight) continue;
993 }
994
995 tseen[pt] = true;
996 wtrans.push_back(pt);
997 }
998 }
999
1000 for(auto pt : place.consumers)
1001 {
1002 if(!tseen[pt] && (!remove_consumers || placeInQuery[arc.place] > 0))
1003 {
1004 tseen[pt] = true;
1005 wtrans.push_back(pt);
1006 }
1007 }
1008 }
1009 pseen[arc.place] = true;
1010 }
1011 }
1012
1013 for(size_t t = 0; t < parent->numberOfTransitions(); ++t)
1014 {
1015 if(!tseen[t] && !parent->_transitions[t].skip)
1016 {
1017 skipTransition(t);
1018 reduced = true;
1019 }
1020 }
1021
1022 for(size_t p = 0; p < parent->numberOfPlaces(); ++p)
1023 {
1024 if(!pseen[p] && !parent->_places[p].skip && placeInQuery[p] == 0)
1025 {
1026 assert(placeInQuery[p] == 0);
1027 skipPlace(p);
1028 reduced = true;
1029 }
1030 }
1031 924
1032 if(reduced)925 if(reduced)
1033 ++_ruleI;926 ++_ruleI;
@@ -1565,6 +1458,153 @@
1565 }1458 }
1566 return continueReductions;1459 return continueReductions;
1567 }1460 }
1461
1462 bool Reducer::ReducebyRuleK(uint32_t *placeInQuery, bool remove_consumers) {
1463 bool reduced = false;
1464 auto opt = relevant(placeInQuery, remove_consumers);
1465 if (!opt)
1466 return false;
1467 auto[tseen, pseen] = opt.value();
1468 for (std::size_t p = 0; p < parent->numberOfPlaces(); ++p) {
1469 if (placeInQuery[p] != 0)
1470 pseen[p] = true;
1471 }
1472
1473 for (std::size_t t = 0; t < parent->numberOfTransitions(); ++t) {
1474 auto transition = parent->_transitions[t];
1475 if (!tseen[t] && !transition.skip && !transition.inhib && transition.pre.size() == 1 &&
1476 transition.post.size() == 1
1477 && transition.pre[0].place == transition.post[0].place) {
1478 auto p = transition.pre[0].place;
1479 if (!pseen[p] && !parent->_places[p].inhib) {
1480 if (parent->initialMarking[p] >= transition.pre[0].weight){
1481 //Mark the initially marked self loop as relevant.
1482 tseen[t] = true;
1483 pseen[p] = true;
1484 reduced |= remove_irrelevant(placeInQuery, tseen, pseen);
1485 _ruleK++;
1486 return reduced;
1487 }
1488 if (transition.pre[0].weight == 1){
1489 for (auto t2 : parent->_places[p].consumers) {
1490 auto transition2 = parent->_transitions[t2];
1491 if (t != t2 && !tseen[t2] && !transition2.skip) {
1492 skipTransition(t2);
1493 reduced = true;
1494 _ruleK++;
1495 }
1496 }
1497 }
1498 }
1499 }
1500 }
1501 return reduced;
1502 }
1503
1504 std::optional<std::pair<std::vector<bool>, std::vector<bool>>>
1505 Reducer::relevant(const uint32_t *placeInQuery, bool remove_consumers) {
1506 std::vector<uint32_t> wtrans;
1507 std::vector<bool> tseen(parent->numberOfTransitions(), false);
1508 for (uint32_t p = 0; p < parent->numberOfPlaces(); ++p) {
1509 if (hasTimedout()) return std::nullopt;
1510 if (placeInQuery[p] > 0) {
1511 const Place &place = parent->_places[p];
1512 for (auto t : place.consumers) {
1513 if (!tseen[t]) {
1514 wtrans.push_back(t);
1515 tseen[t] = true;
1516 }
1517 }
1518 for (auto t : place.producers) {
1519 if (!tseen[t]) {
1520 wtrans.push_back(t);
1521 tseen[t] = true;
1522 }
1523 }
1524 }
1525 }
1526 std::vector<bool> pseen(parent->numberOfPlaces(), false);
1527
1528 while (!wtrans.empty()) {
1529 if (hasTimedout()) return std::nullopt;
1530 auto t = wtrans.back();
1531 wtrans.pop_back();
1532 const Transition &trans = parent->_transitions[t];
1533 for (const Arc &arc : trans.pre) {
1534 const Place &place = parent->_places[arc.place];
1535 if (arc.inhib) {
1536 for (auto pt : place.consumers) {
1537 if (!tseen[pt]) {
1538 Transition &trans = parent->_transitions[pt];
1539 auto it = trans.post.begin();
1540 for (; it != trans.post.end(); ++it)
1541 if (it->place >= arc.place) break;
1542 if (it != trans.post.end() && it->place == arc.place) {
1543 auto it2 = trans.pre.begin();
1544 for (; it2 != trans.pre.end(); ++it2)
1545 if (it2->place >= arc.place || it2->inhib) break;
1546 if (it->weight <= it2->weight) continue;
1547 }
1548 tseen[pt] = true;
1549 wtrans.push_back(pt);
1550 }
1551 }
1552 } else {
1553 for (auto pt : place.producers) {
1554 if (!tseen[pt]) {
1555 Transition &trans = parent->_transitions[pt];
1556 auto it = trans.pre.begin();
1557 for (; it != trans.pre.end(); ++it)
1558 if (it->place >= arc.place) break;
1559
1560 if (it != trans.pre.end() && it->place == arc.place && !it->inhib) {
1561 auto it2 = trans.post.begin();
1562 for (; it2 != trans.post.end(); ++it2)
1563 if (it2->place >= arc.place) break;
1564 if (it->weight >= it2->weight) continue;
1565 }
1566
1567 tseen[pt] = true;
1568 wtrans.push_back(pt);
1569 }
1570 }
1571
1572 for (auto pt : place.consumers) {
1573 if (!tseen[pt] && (!remove_consumers || placeInQuery[arc.place] > 0)) {
1574 tseen[pt] = true;
1575 wtrans.push_back(pt);
1576 }
1577 }
1578 }
1579 pseen[arc.place] = true;
1580 }
1581 }
1582 return std::make_optional(std::pair(tseen, pseen));
1583 }
1584
1585 bool Reducer::remove_irrelevant(const uint32_t* placeInQuery, const std::vector<bool> &tseen, const std::vector<bool> &pseen) {
1586 bool reduced = false;
1587 for(size_t t = 0; t < parent->numberOfTransitions(); ++t)
1588 {
1589 if(!tseen[t] && !parent->_transitions[t].skip)
1590 {
1591 skipTransition(t);
1592 reduced = true;
1593 }
1594 }
1595
1596 for(size_t p = 0; p < parent->numberOfPlaces(); ++p)
1597 {
1598 if(!pseen[p] && !parent->_places[p].skip && placeInQuery[p] == 0)
1599 {
1600 assert(placeInQuery[p] == 0);
1601 skipPlace(p);
1602 reduced = true;
1603 }
1604 }
1605 return reduced;
1606 }
1607
1568 void Reducer::Reduce(QueryPlaceAnalysisContext& context, int enablereduction, bool reconstructTrace, int timeout, bool remove_loops, bool remove_consumers, bool next_safe, std::vector<uint32_t>& reduction) {1608 void Reducer::Reduce(QueryPlaceAnalysisContext& context, int enablereduction, bool reconstructTrace, int timeout, bool remove_loops, bool remove_consumers, bool next_safe, std::vector<uint32_t>& reduction) {
15691609
1570 this->_timeout = timeout;1610 this->_timeout = timeout;
@@ -1603,6 +1643,7 @@
1603 if(!remove_loops) 1643 if(!remove_loops)
1604 while(ReducebyRuleI(context.getQueryPlaceCount(), remove_loops, remove_consumers)) changed = true;1644 while(ReducebyRuleI(context.getQueryPlaceCount(), remove_loops, remove_consumers)) changed = true;
1605 while(ReducebyRuleD(context.getQueryPlaceCount())) changed = true;1645 while(ReducebyRuleD(context.getQueryPlaceCount())) changed = true;
1646 changed |= ReducebyRuleK(context.getQueryPlaceCount(), remove_consumers);
1606 }1647 }
1607 } while(changed && !hasTimedout());1648 } while(changed && !hasTimedout());
1608 if(!next_safe) 1649 if(!next_safe)
@@ -1622,7 +1663,7 @@
1622 }1663 }
1623 else1664 else
1624 {1665 {
1625 const char* rnames = "ABCDEFGHIJ";1666 const char* rnames = "ABCDEFGHIJK";
1626 for(int i = reduction.size() - 1; i >= 0; --i)1667 for(int i = reduction.size() - 1; i >= 0; --i)
1627 {1668 {
1628 if(next_safe)1669 if(next_safe)
@@ -1683,6 +1724,9 @@
1683 case 9:1724 case 9:
1684 while(ReducebyRuleJ(context.getQueryPlaceCount())) changed = true;1725 while(ReducebyRuleJ(context.getQueryPlaceCount())) changed = true;
1685 break;1726 break;
1727 case 10:
1728 if (ReducebyRuleK(context.getQueryPlaceCount(), remove_consumers)) changed = true;
1729 break;
1686 }1730 }
1687#ifndef NDEBUG1731#ifndef NDEBUG
1688 auto end = std::chrono::high_resolution_clock::now();1732 auto end = std::chrono::high_resolution_clock::now();
16891733
=== modified file 'src/VerifyPN.cpp'
--- src/VerifyPN.cpp 2021-02-04 11:16:09 +0000
+++ src/VerifyPN.cpp 2021-02-18 12:06:25 +0000
@@ -204,7 +204,7 @@
204 for(auto& qn : q)204 for(auto& qn : q)
205 {205 {
206 int32_t n;206 int32_t n;
207 if(sscanf(qn.c_str(), "%d", &n) != 1 || n < 0 || n > 9)207 if(sscanf(qn.c_str(), "%d", &n) != 1 || n < 0 || n > 10)
208 {208 {
209 std::cerr << "Error in reduction rule choice : " << qn << std::endl;209 std::cerr << "Error in reduction rule choice : " << qn << std::endl;
210 return ErrorCode;210 return ErrorCode;

Subscribers

People subscribed via source and target branches

to all changes: