101
138
void ColoredPetriNetBuilder::sort() {
141
//----------------------- Color fixpoint -----------------------//
143
void ColoredPetriNetBuilder::printPlaceTable() {
144
for (auto place: _places) {
145
auto placeID = _placenames[place.name];
146
auto placeColorFixpoint = _placeColorFixpoints[placeID];
147
std::cout << "Place: " << place.name << " in queue: " << placeColorFixpoint.inQueue << " with colortype " << place.type->getName() << std::endl;
149
for(auto fixpointPair : placeColorFixpoint.constraints._intervals) {
151
for(auto range : fixpointPair._ranges) {
152
std::cout << range._lower << "-" << range._upper << ", ";
154
std::cout << "]"<< std::endl;
156
std::cout << std::endl;
160
void ColoredPetriNetBuilder::computePlaceColorFixpoint(uint32_t maxIntervals, uint32_t maxIntervalsReduced, int32_t timeout) {
161
//Start timers for timing color fixpoint creation and max interval reduction steps
162
auto start = std::chrono::high_resolution_clock::now();
163
std::chrono::_V2::system_clock::time_point end = std::chrono::high_resolution_clock::now();
164
auto reduceTimer = std::chrono::high_resolution_clock::now();
165
while(!_placeFixpointQueue.empty()){
166
uint32_t currentPlaceId = _placeFixpointQueue.back();
167
//Reduce max interval once timeout passes
168
if(timeout > 0 && std::chrono::duration_cast<std::chrono::seconds>(end - reduceTimer).count() >= timeout){
169
maxIntervals = maxIntervalsReduced;
170
reduceTimer = std::chrono::high_resolution_clock::now();
173
_placeFixpointQueue.pop_back();
174
_placeColorFixpoints[currentPlaceId].inQueue = false;
175
std::vector<uint32_t> connectedTransitions = _placePostTransitionMap[currentPlaceId];
177
for (uint32_t transitionId : connectedTransitions) {
178
Colored::Transition& transition = _transitions[transitionId];
179
// Skip transitions that cannot add anything new,
180
// such as transitions with only constants on their arcs that have been processed once
181
if (transition.considered) continue;
182
bool transitionActivated = true;
183
transition.variableMaps.clear();
185
if(!_arcIntervals.count(transitionId)){
186
_arcIntervals[transitionId] = setupTransitionVars(transition);
188
processInputArcs(transition, currentPlaceId, transitionId, transitionActivated, maxIntervals);
190
//If there were colors which activated the transitions, compute the intervals produced
191
if (transitionActivated) {
192
processOutputArcs(transition);
195
end = std::chrono::high_resolution_clock::now();
198
_fixPointCreationTime = (std::chrono::duration_cast<std::chrono::microseconds>(end - start).count())*0.000001;
201
_placeColorFixpoints.clear();
204
//Create Arc interval structures for the transition
205
std::unordered_map<uint32_t, Colored::ArcIntervals> ColoredPetriNetBuilder::setupTransitionVars(Colored::Transition transition){
206
std::unordered_map<uint32_t, Colored::ArcIntervals> res;
207
for(auto arc : transition.input_arcs){
208
std::set<const Colored::Variable *> variables;
209
std::unordered_map<uint32_t, const Colored::Variable *> varPositions;
210
std::unordered_map<const Colored::Variable *, std::vector<std::unordered_map<uint32_t, int32_t>>> varModifiersMap;
211
arc.expr->getVariables(variables, varPositions, varModifiersMap);
213
Colored::ArcIntervals newArcInterval(&_placeColorFixpoints[arc.place], varModifiersMap);
214
res[arc.place] = newArcInterval;
219
//Retrieve color intervals for the input arcs based on their places
220
void ColoredPetriNetBuilder::getArcIntervals(Colored::Transition& transition, bool &transitionActivated, uint32_t max_intervals, uint32_t transitionId){
221
for (auto arc : transition.input_arcs) {
222
PetriEngine::Colored::ColorFixpoint& curCFP = _placeColorFixpoints[arc.place];
224
curCFP.constraints.restrict(max_intervals);
225
_maxIntervals = std::max(_maxIntervals, (uint32_t) curCFP.constraints.size());
227
Colored::ArcIntervals& arcInterval = _arcIntervals[transitionId][arc.place];
229
arcInterval._intervalTupleVec.clear();
231
if(!arc.expr->getArcIntervals(arcInterval, curCFP, &index, 0)){
232
transitionActivated = false;
238
void removeInvalidVarmaps(Colored::Transition& transition){
239
std::vector<std::unordered_map<const Colored::Variable *, Colored::intervalTuple_t>> newVarmaps;
240
for(auto& varMap : transition.variableMaps){
241
bool validVarMap = true;
242
for(auto& varPair : varMap){
243
if(!varPair.second.hasValidIntervals()){
247
varPair.second.simplify();
251
newVarmaps.push_back(std::move(varMap));
254
transition.variableMaps = std::move(newVarmaps);
257
//Retreive interval colors from the input arcs restricted by the transition guard
258
void ColoredPetriNetBuilder::processInputArcs(Colored::Transition& transition, uint32_t currentPlaceId, uint32_t transitionId, bool &transitionActivated, uint32_t max_intervals) {
261
getArcIntervals(transition, transitionActivated, max_intervals, transitionId);
264
if(!transitionActivated){
267
if(intervalGenerator.getVarIntervals(transition.variableMaps, _arcIntervals[transitionId])){
268
if(transition.guard != nullptr) {
269
transition.guard->restrictVars(transition.variableMaps);
270
removeInvalidVarmaps(transition);
272
if(transition.variableMaps.empty()){
273
//Guard restrictions removed all valid intervals
274
transitionActivated = false;
279
//Retrieving variable intervals failed
280
transitionActivated = false;
284
void ColoredPetriNetBuilder::processOutputArcs(Colored::Transition& transition) {
285
bool transitionHasVarOutArcs = false;
287
for (auto& arc : transition.output_arcs) {
288
Colored::ColorFixpoint& placeFixpoint = _placeColorFixpoints[arc.place];
289
//used to check if colors are added to the place. The total distance between upper and
290
//lower bounds should grow when more colors are added and as we cannot remove colors this
291
//can be checked by summing the differences
292
uint32_t colorsBefore = placeFixpoint.constraints.getContainedColors();
294
std::set<const Colored::Variable *> variables;
295
arc.expr->getVariables(variables);
297
if (!variables.empty()) {
298
transitionHasVarOutArcs = true;
301
auto intervals = arc.expr->getOutputIntervals(transition.variableMaps);
302
intervals.simplify();
304
for(auto& interval : intervals._intervals){
305
placeFixpoint.constraints.addInterval(std::move(interval));
308
//Check if the place should be added to the queue
309
if (!placeFixpoint.inQueue) {
310
uint32_t colorsAfter = placeFixpoint.constraints.getContainedColors();
311
if (colorsAfter > colorsBefore) {
312
_placeFixpointQueue.push_back(arc.place);
313
placeFixpoint.inQueue = true;
317
//If there are no variables among the out arcs of a transition
318
// and it has been activated, there is no reason to cosider it again
319
if(!transitionHasVarOutArcs) {
320
transition.considered = true;
324
//----------------------- Unfolding -----------------------//
105
326
PetriNetBuilder& ColoredPetriNetBuilder::unfold() {
106
327
if (_stripped) assert(false);
107
328
if (_isColored && !_unfolded) {
108
329
auto start = std::chrono::high_resolution_clock::now();
109
for (auto& place : _places) {
113
331
for (auto& transition : _transitions) {
114
332
unfoldTransition(transition);
334
auto unfoldedPlaceMap = _ptBuilder.getPlaceNames();
335
for (auto& place : _places) {
336
handleOrphanPlace(place, unfoldedPlaceMap);
117
338
_unfolded = true;
118
339
auto end = std::chrono::high_resolution_clock::now();
119
340
_time = (std::chrono::duration_cast<std::chrono::microseconds>(end - start).count())*0.000001;
122
342
return _ptBuilder;
125
void ColoredPetriNetBuilder::unfoldPlace(Colored::Place& place) {
126
for (size_t i = 0; i < place.type->size(); ++i) {
127
std::string name = place.name + ";" + std::to_string(i);
128
const Colored::Color* color = &place.type->operator[](i);
129
_ptBuilder.addPlace(name, place.marking[color], 0.0, 0.0);
130
_ptplacenames[place.name][color->getId()] = std::move(name);
345
//Due to the way we unfold places, we only unfold palces connected to an arc (which makes sense)
346
//However, in queries asking about orphan places it cannot find these, as they have not been unfolded
347
//so we make a placeholder place which just has tokens equal to the number of colored tokens
348
//Ideally, orphan places should just be translated to a constant in the query
349
void ColoredPetriNetBuilder::handleOrphanPlace(Colored::Place& place, std::unordered_map<std::string, uint32_t> unfoldedPlaceMap) {
350
if(_ptplacenames.count(place.name) <= 0){
352
std::string name = place.name + "_orphan";
353
_ptBuilder.addPlace(name, place.marking.size(), 0.0, 0.0);
354
_ptplacenames[place.name][0] = std::move(name);
356
uint32_t usedTokens = 0;
358
for(std::pair<const uint32_t, std::string> unfoldedPlace : _ptplacenames[place.name]){
359
auto unfoldedMarking = _ptBuilder.initMarking();
361
auto unfoldedPlaceId = unfoldedPlaceMap[unfoldedPlace.second];
362
usedTokens += unfoldedMarking[unfoldedPlaceId];
365
if(place.marking.size() > usedTokens){
366
std::string name = place.name + "_orphan";
367
_ptBuilder.addPlace(name, place.marking.size() - usedTokens, 0.0, 0.0);
368
_ptplacenames[place.name][UINT32_MAX] = std::move(name);
375
void ColoredPetriNetBuilder::unfoldPlace(const Colored::Place* place, const PetriEngine::Colored::Color *color) {
376
std::string name = place->name + "_" + std::to_string(color->getId());
377
_ptBuilder.addPlace(name, place->marking[color], 0.0, 0.0);
378
_ptplacenames[place->name][color->getId()] = std::move(name);
135
382
void ColoredPetriNetBuilder::unfoldTransition(Colored::Transition& transition) {
136
BindingGenerator gen(transition, _arcs, _colors);
383
FixpointBindingGenerator gen(transition, _colors);
138
for (auto& b : gen) {
139
std::string name = transition.name + ";" + std::to_string(i++);
386
std::string name = transition.name + "_" + std::to_string(i++);
140
387
_ptBuilder.addTransition(name, 0.0, 0.0);
141
388
_pttransitionnames[transition.name].push_back(name);
142
389
++_npttransitions;
143
for (auto& arc : transition.arcs) {
144
unfoldArc(arc, b, name);
390
for (auto& arc : transition.input_arcs) {
391
unfoldArc(arc, b, name, true );
393
for (auto& arc : transition.output_arcs) {
394
unfoldArc(arc, b, name, false);
149
void ColoredPetriNetBuilder::unfoldArc(Colored::Arc& arc, Colored::ExpressionContext::BindingMap& binding, std::string& tName) {
399
void ColoredPetriNetBuilder::unfoldArc(Colored::Arc& arc, Colored::ExpressionContext::BindingMap& binding, std::string& tName, bool input) {
150
400
Colored::ExpressionContext context {binding, _colors};
151
auto ms = arc.expr->eval(context);
401
auto ms = arc.expr->eval(context);
153
403
for (const auto& color : ms) {
154
404
if (color.second == 0) {
157
const std::string& pName = _ptplacenames[_places[arc.place].name][color.first->getId()];
407
const PetriEngine::Colored::Place& place = _places[arc.place];
408
const std::string& pName = _ptplacenames[place.name][color.first->getId()];
410
unfoldPlace(&place, color.first);
159
413
_ptBuilder.addInputArc(pName, tName, false, color.second);
202
464
return !arc.input ? "(" + _transitions[arc.transition].name + ", " + _places[arc.place].name + ")" :
203
465
"(" + _places[arc.place].name + ", " + _transitions[arc.transition].name + ")";
206
BindingGenerator::Iterator::Iterator(BindingGenerator* generator)
207
: _generator(generator)
211
bool BindingGenerator::Iterator::operator==(Iterator& other) {
212
return _generator == other._generator;
215
bool BindingGenerator::Iterator::operator!=(Iterator& other) {
216
return _generator != other._generator;
219
BindingGenerator::Iterator& BindingGenerator::Iterator::operator++() {
220
_generator->nextBinding();
221
if (_generator->isInitial()) _generator = nullptr;
225
const Colored::ExpressionContext::BindingMap BindingGenerator::Iterator::operator++(int) {
226
auto prev = _generator->currentBinding();
231
Colored::ExpressionContext::BindingMap& BindingGenerator::Iterator::operator*() {
232
return _generator->currentBinding();
235
BindingGenerator::BindingGenerator(Colored::Transition& transition,
236
const std::vector<Colored::Arc>& arcs,
237
ColoredPetriNetBuilder::ColorTypeMap& colorTypes)
238
: _colorTypes(colorTypes)
240
_expr = transition.guard;
241
std::set<Colored::Variable*> variables;
242
if (_expr != nullptr) {
243
_expr->getVariables(variables);
245
for (auto arc : transition.arcs) {
246
assert(arc.expr != nullptr);
247
arc.expr->getVariables(variables);
249
for (auto var : variables) {
250
_bindings[var->name] = &var->colorType->operator[](0);
257
bool BindingGenerator::eval() {
258
if (_expr == nullptr)
261
Colored::ExpressionContext context {_bindings, _colorTypes};
262
return _expr->eval(context);
265
Colored::ExpressionContext::BindingMap& BindingGenerator::nextBinding() {
268
for (auto& _binding : _bindings) {
269
_binding.second = &_binding.second->operator++();
270
if (_binding.second->getId() != 0) {
283
Colored::ExpressionContext::BindingMap& BindingGenerator::currentBinding() {
287
bool BindingGenerator::isInitial() const {
288
for (auto& b : _bindings) {
289
if (b.second->getId() != 0) return false;
294
BindingGenerator::Iterator BindingGenerator::begin() {
298
BindingGenerator::Iterator BindingGenerator::end() {
b'\\ No newline at end of file'