2
* Copyright Peter G. Jensen, all rights reserved.
7
* Author: Peter G. Jensen <root@petergjoel.dk>
9
* Created on April 2, 2020, 6:03 PM
12
#include "PetriEngine/TAR/TraceSet.h"
17
namespace Reachability
20
void inline_union(std::vector<size_t>& into, const std::vector<size_t>& other)
22
into.reserve(into.size() + other.size());
23
auto iit = into.begin();
24
auto oit = other.begin();
26
while (oit != other.end()) {
27
while (iit != into.end() && *iit < *oit) ++iit;
28
if (iit == into.end()) {
29
into.insert(iit, oit, other.end());
32
else if (*iit != *oit) {
33
iit = into.insert(iit, *oit);
39
TraceSet::TraceSet(const PetriNet& net)
48
prvector_t falserange;
50
for (size_t v = 0; v < _net.numberOfPlaces(); ++v)
51
falserange.find_or_add(v) &= 0;
53
assert(falserange.is_false(_net.numberOfPlaces()));
54
assert(truerange.is_true());
55
assert(!falserange.is_true());
56
assert(falserange.is_false(_net.numberOfPlaces()));
57
assert(truerange.compare(falserange).first);
58
assert(!truerange.compare(falserange).second);
59
assert(falserange.compare(truerange).second);
60
assert(!falserange.compare(truerange).first);
61
_states.emplace_back(falserange); // false
62
_states.emplace_back(truerange); // true
65
assert(_states[1].simulates.size() == 0);
66
assert(_states[1].simulators.size() == 1);
67
assert(_states[0].simulates.size() == 1);
68
assert(_states[0].simulators.size() == 0);
70
assert(_states[1].simulators[0] == 0);
71
assert(_states[0].simulates[0] == 1);
73
_intmap.emplace(falserange, 0);
74
_intmap.emplace(truerange, 1);
79
void TraceSet::clear()
88
std::set<size_t> TraceSet::minimize(const std::set<size_t>& org) const
90
std::set<size_t> minimal = org;
92
for(auto e : _states[i].simulates)
97
void TraceSet::copyNonChanged(const std::set<size_t>& from, const std::vector<int64_t>& modifiers, std::set<size_t>& to) const
100
if (!_states[p].interpolant.restricts(modifiers))
104
std::set<size_t> TraceSet::maximize(const std::set<size_t>& org) const
109
maximal.insert(_states[i].simulates.begin(), _states[i].simulates.end());
113
std::pair<bool, size_t> TraceSet::stateForPredicate(prvector_t& predicate)
115
predicate.compress();
116
assert(predicate.is_compact());
117
if (predicate.is_true()) {
118
return std::make_pair(false, 1);
120
else if (predicate.is_false(_net.numberOfPlaces())) {
121
return std::make_pair(false, 0);
124
auto astate = _states.size();
125
auto res = _intmap.emplace(predicate, astate);
128
if (!(_states[res.first->second].interpolant == predicate)) {
129
assert(!(_states[res.first->second].interpolant < predicate));
130
assert(!(predicate < _states[res.first->second].interpolant));
133
for (auto& e : _intmap) {
134
assert(e.first == _states[e.second].interpolant);
137
return std::make_pair(false, res.first->second);
140
_states.emplace_back(predicate);
141
computeSimulation(astate);
142
res.first->second = astate;
143
assert(_states[astate].interpolant == predicate);
145
for (auto& s : _states) {
146
if (s.interpolant == predicate) {
147
if (&s == &_states[astate]) continue;
148
assert((s.interpolant < predicate) ||
149
(predicate < s.interpolant));
153
for (auto& e : _intmap) {
154
assert(e.first == _states[e.second].interpolant);
158
for(auto& r : predicate._ranges)
161
if(_net.initial()[r._place] > r._range._upper ||
162
_net.initial()[r._place] < r._range._lower)
170
auto lb = std::lower_bound(_initial.begin(), _initial.end(), astate);
171
if (lb == std::end(_initial) || *lb != res.second)
173
_initial.insert(lb, astate);
176
// check which edges actually change the predicate, add rest to automata
177
for(size_t t = 0; t < _net.numberOfTransitions(); ++t)
179
auto pre = _net.preset(t);
181
bool changes = false;
182
for(; pre.first != pre.second; ++pre.first)
184
auto it = predicate[pre.first->place];
188
auto post = _net.postset(t);
189
int64_t change = pre.first->tokens;
190
if(pre.first->tokens > it->_range._upper)
191
_states[astate].add_edge(t+1, 0);
193
for(; post.first != post.second; ++post.first)
195
if(post.first->place == pre.first->place)
197
change += post.first->tokens;
201
if(change < 0 && !it->_range.no_lower())
203
else if(change > 0 && !it->_range.no_upper())
209
auto post = _net.postset(t);
210
for(; post.first != post.second; ++post.first)
212
auto it = predicate[post.first->place];
216
auto pre = _net.preset(t);
217
int64_t change = post.first->tokens;
218
for(; pre.first != pre.second; ++pre.first)
220
if(pre.first->place == post.first->place)
222
change -= pre.first->tokens;
226
if(change < 0 && !it->_range.no_lower())
228
else if(change > 0 && !it->_range.no_upper())
236
_states[astate].add_edge(t+1, astate);
241
return std::make_pair(true, astate);
245
void TraceSet::computeSimulation(size_t index)
247
AutomataState& state = _states[index];
248
assert(index == _states.size() - 1 || index == 0);
249
for (size_t i = 0; i < _states.size(); ++i) {
250
if (i == index) continue;
251
AutomataState& other = _states[i];
252
std::pair<bool, bool> res = other.interpolant.compare(state.interpolant);
253
assert(!res.first || !res.second);
255
state.simulates.emplace_back(i);
256
auto lb = std::lower_bound(other.simulators.begin(), other.simulators.end(), index);
257
if (lb == std::end(other.simulators) || *lb != index)
258
other.simulators.insert(lb, index);
259
other.interpolant.compare(state.interpolant);
262
state.simulators.emplace_back(i);
263
auto lb = std::lower_bound(other.simulates.begin(), other.simulates.end(), index);
264
if (lb == std::end(other.simulates) || *lb != index)
265
other.simulates.insert(lb, index);
266
other.interpolant.compare(state.interpolant);
270
assert(_states[1].simulates.size() == 0);
271
assert(_states[0].simulators.size() == 0);
274
bool TraceSet::follow(const std::set<size_t>& from, std::set<size_t>& nextinter, size_t symbol)
277
for (size_t i : from) {
282
AutomataState& as = _states[i];
283
if (as.is_accepting()) {
288
auto it = as.first_edge(symbol);
290
while (it != as.get_edges().end()) {
291
if (it->edge != symbol) {
296
assert(ae.to.size() > 0);
297
if (ae.to.front() == 0)
299
nextinter.insert(ae.to.begin(), ae.to.end());
305
void TraceSet::removeEdges(size_t edge)
307
for(auto& s : _states)
311
// TODO back color here to remove non-accepting end-components.
314
bool TraceSet::addTrace(std::vector<std::pair<prvector_t, size_t>>& inter)
316
assert(inter.size() > 0);
321
auto res = stateForPredicate(inter[0].first);
324
//inter[0].first.print(std::cerr) << std::endl;
327
bool added_terminal = false;
329
for (size_t i = 0; i < inter.size(); ++i) {
331
// std::cerr << " >> T" << inter[i].second << " <<" << std::endl;
332
if (j == inter.size()) {
333
some |= _states[last].add_edge(inter[i].second, 0);
335
added_terminal = true;
337
// std::cerr << "FALSE" << std::endl;
340
// inter[j].first.print(std::cerr) << std::endl;
341
/*if (!inter[i].second)
342
trace[j].add_interpolant(last);
344
auto res = stateForPredicate(inter[j].first);
346
// assert(inter[i].second || res.second == last);
347
some |= _states[last].add_edge(inter[i].second, res.second);
352
assert(added_terminal);
356
std::ostream& TraceSet::print(std::ostream& out) const
358
out << "digraph graphname {\n";
359
for (size_t i = 0; i < _states.size(); ++i) {
360
auto& s = _states[i];
361
out << "\tS" << i << " [label=\"";
362
if (s.interpolant.is_true()) {
365
else if (s.interpolant.is_false(_net.numberOfPlaces())) {
369
s.interpolant.print(out);
372
auto lb = std::lower_bound(_initial.begin(), _initial.end(), i);
373
if (lb != std::end(_initial) && *lb == i)
374
out << "box,color=green";
379
for (size_t i = 0; i < _states.size(); ++i) {
380
auto& s = _states[i];
381
for (auto& e : s.get_edges()) {
382
out << "\tS" << i << "_" << e.edge << " [label=\"" <<
383
(e.edge == 0 ? "Q" : std::to_string(e.edge - 1))
384
<< "\",shape=diamond,style=dashed];\n";
385
out << "\tS" << i << " -> S" << i << "_" << e.edge << ";\n";
386
for (auto& t : e.to) {
387
out << "\tS" << i << "_" << e.edge << " -> S" << t << ";\n";