7
7
namespace PetriEngine {
10
PartitionBuilder::PartitionBuilder(std::vector<Transition> *transitions, std::vector<Place> *places, std::unordered_map<uint32_t,std::vector<uint32_t>> *placePostTransitionMap, std::unordered_map<uint32_t,std::vector<uint32_t>> *placePreTransitionMap)
11
: _transitions(transitions), _places(places), _placePostTransitionMap(placePostTransitionMap), _placePreTransitionMap(placePreTransitionMap) {
13
//Instantiate partitions
14
for(uint32_t i = 0; i < _places->size(); i++){
15
auto place = _places->operator[](i);
16
interval_t fullInterval = place.type->getFullInterval();
17
EquivalenceClass fullClass = EquivalenceClass(place.type);
18
fullClass._colorIntervals.addInterval(fullInterval);
19
_partition[i]._equivalenceClasses.push_back(fullClass);
20
_placeQueue.push_back(i);
25
PartitionBuilder::PartitionBuilder(std::vector<Transition> *transitions, std::vector<Place> *places, std::unordered_map<uint32_t,std::vector<uint32_t>> *placePostTransitionMap, std::unordered_map<uint32_t,std::vector<uint32_t>> *placePreTransitionMap, std::vector<Colored::ColorFixpoint> *placeColorFixpoints)
26
: _transitions(transitions), _places(places), _placePostTransitionMap(placePostTransitionMap), _placePreTransitionMap(placePreTransitionMap) {
28
//Instantiate partitions
29
for(uint32_t i = 0; i < _places->size(); i++){
30
auto place = _places->operator[](i);
31
EquivalenceClass fullClass = EquivalenceClass(place.type);
32
fullClass._colorIntervals = placeColorFixpoints->operator[](i).constraints;
33
_partition[i]._equivalenceClasses.push_back(fullClass);
34
_placeQueue.push_back(i);
39
void PartitionBuilder::printPartion() {
40
for(auto equivalenceVec : _partition){
41
std::cout << "Partition for place " << _places->operator[](equivalenceVec.first).name << std::endl;
42
for (auto equivalenceClass : equivalenceVec.second._equivalenceClasses){
10
PartitionBuilder::PartitionBuilder(const std::vector<Transition> &transitions, const std::vector<Place> &places, const std::unordered_map<uint32_t,std::vector<uint32_t>> &placePostTransitionMap, const std::unordered_map<uint32_t,std::vector<uint32_t>> &placePreTransitionMap)
11
: PartitionBuilder(transitions, places, placePostTransitionMap, placePreTransitionMap, nullptr){
14
PartitionBuilder::PartitionBuilder(const std::vector<Transition> &transitions, const std::vector<Place> &places, const std::unordered_map<uint32_t,std::vector<uint32_t>> &placePostTransitionMap, const std::unordered_map<uint32_t,std::vector<uint32_t>> &placePreTransitionMap, const std::vector<Colored::ColorFixpoint> *placeColorFixpoints)
15
: _transitions(transitions), _places(places), _placePostTransitionMap(placePostTransitionMap), _placePreTransitionMap(placePreTransitionMap) {
17
//Instantiate partitions
18
for(uint32_t i = 0; i < _places.size(); i++){
19
const PetriEngine::Colored::Place& place = _places[i];
20
EquivalenceClass fullClass = EquivalenceClass(++_eq_id_counter, place.type);
21
if(placeColorFixpoints != nullptr){
22
fullClass.setIntervalVector(placeColorFixpoints->operator[](i).constraints);
24
fullClass.addInterval(place.type->getFullInterval());
26
_partition[i].push_back_Eqclass(fullClass);
27
for(uint32_t j = 0; j < place.type->productSize(); j++){
28
_partition[i].push_back_diagonalTuplePos(false);
30
_placeQueue.push_back(i);
35
void PartitionBuilder::printPartion() const {
36
for(const auto &equivalenceVec : _partition){
37
std::cout << "Partition for place " << _places[equivalenceVec.first].name << std::endl;
38
std::cout << "Diag variables: (";
39
for(auto daigPos : equivalenceVec.second.getDiagonalTuplePositions()){
40
std::cout << daigPos << ",";
42
std::cout << ")" << std::endl;
43
for (const auto &equivalenceClass : equivalenceVec.second.getEquivalenceClasses()){
43
44
std::cout << equivalenceClass.toString() << std::endl;
46
std::cout << "Diagonal " << equivalenceVec.second.diagonal << std::endl << std::endl;;
47
std::cout << "Diagonal " << equivalenceVec.second.isDiagonal() << std::endl << std::endl;;
50
void PartitionBuilder::partitionNet(){
51
bool PartitionBuilder::partitionNet(int32_t timeout) {
52
const auto start = std::chrono::high_resolution_clock::now();
51
53
handleLeafTransitions();
54
auto end = std::chrono::high_resolution_clock::now();
53
while(!_placeQueue.empty()){
56
while(!_placeQueue.empty() && timeout > 0 && std::chrono::duration_cast<std::chrono::seconds>(end - start).count() < timeout){
54
57
auto placeId = _placeQueue.back();
55
58
_placeQueue.pop_back();
56
59
_inQueue[placeId] = false;
58
auto place = _places->operator[](placeId);
61
bool allPositionsDiagonal = true;
62
for(auto diag : _partition[placeId].getDiagonalTuplePositions()){
64
allPositionsDiagonal = false;
60
for(uint32_t transitionId : _placePreTransitionMap->operator[](placeId)){
61
//std::cout << "For transition " << _transitions->operator[](transitionId).name << " and place " << _places->operator[](placeId).name << std::endl;
64
handleTransition(transitionId, placeId);
66
//std::cout << "---------------------------------------------------" << std::endl;
69
if(allPositionsDiagonal || _partition[placeId].getEquivalenceClasses().size() >=
70
_partition[placeId].getEquivalenceClasses().back().type()->size(_partition[placeId].getDiagonalTuplePositions())){
71
_partition[placeId].setDiagonal(true);
73
if(_placePreTransitionMap.find(placeId) != _placePreTransitionMap.end()){
74
for(uint32_t transitionId : _placePreTransitionMap.find(placeId)->second){
75
handleTransition(transitionId, placeId);
78
end = std::chrono::high_resolution_clock::now();
80
return _placeQueue.empty();
71
void PartitionBuilder::assignColorMap(std::unordered_map<uint32_t, EquivalenceVec> &partition){
83
void PartitionBuilder::assignColorMap(std::unordered_map<uint32_t, EquivalenceVec> &partition) const{
72
84
for(auto& eqVec : partition){
73
if(eqVec.second.diagonal){
85
if(eqVec.second.isDiagonal()){
76
ColorType *colorType = _places->operator[](eqVec.first).type;
88
const ColorType *colorType = _places[eqVec.first].type;
77
89
for(uint32_t i = 0; i < colorType->size(); i++){
78
const Color *color = &colorType->operator[](i);
79
for(auto& eqClass : eqVec.second._equivalenceClasses){
80
std::vector<uint32_t> colorIds;
81
color->getTupleId(&colorIds);
82
if(eqClass.containsColor(colorIds)){
83
eqVec.second.colorEQClassMap[color] = &eqClass;
90
const Color *color = &(*colorType)[i];
91
eqVec.second.addColorToEqClassMap(color);
90
96
void PartitionBuilder::handleTransition(uint32_t transitionId, uint32_t postPlaceId){
91
auto transition = _transitions->operator[](transitionId);
97
const PetriEngine::Colored::Transition &transition = _transitions[transitionId];
93
99
bool arcFound = false;
94
for(auto& outArc : transition.output_arcs){
100
for(const auto& outArc : transition.output_arcs){
95
101
if(outArc.place == postPlaceId){
106
handleTransition(&transition, postPlaceId, &postArc);
112
handleTransition(transition, postPlaceId, &postArc);
109
void PartitionBuilder::handleTransition(Transition *transition, uint32_t postPlaceId, Arc *postArc) {
110
std::unordered_map<const PetriEngine::Colored::Variable *, std::vector<std::unordered_map<uint32_t, int32_t>>> varModifierMap;
111
std::unordered_map<uint32_t, const PetriEngine::Colored::Variable *> varPositionMap;
112
std::set<const PetriEngine::Colored::Variable *> postArcVars;
113
std::set<const PetriEngine::Colored::Variable *>guardVars;
114
std::set<const Colored::Variable*> diagonalVars;
116
postArc->expr->getVariables(postArcVars, varPositionMap, varModifierMap);
118
for(auto varModMap : varModifierMap){
115
//Check if a variable appears more than once on the output arc
116
//If the place is does not have a product colortype mark the whole place as diagonal, otherwise only the positions
117
void PartitionBuilder::checkVarOnArc(const VariableModifierMap &varModifierMap, std::set<const Colored::Variable*> &diagonalVars, uint32_t placeId, bool inputArc){
118
for(const auto &varModMap : varModifierMap){
119
119
if(varModMap.second.size() > 1){
120
120
uint32_t actualSize = 0;
121
for(auto map : varModMap.second){
121
std::vector<uint32_t> positions;
122
for(const auto &map : varModMap.second){
122
123
if(!map.empty()){
124
for(auto position : map){
125
positions.push_back(position.first);
126
130
if(actualSize > 1) {
127
_partition[postPlaceId].diagonal = true;
131
diagonalVars.insert(varModMap.first);
132
if(_partition[placeId].getEquivalenceClasses().back().type()->productSize() == 1){
133
_partition[placeId].setDiagonal(true);
135
for(auto pos : positions){
136
if(!_partition[placeId].getDiagonalTuplePositions()[pos]){
137
if(inputArc) addToQueue(placeId);
138
_partition[placeId].setDiagonalTuplePosition(pos,true);
132
if(transition->guard != nullptr){
133
transition->guard->getVariables(guardVars);
136
auto placePartition = _partition[postPlaceId]._equivalenceClasses;
138
for(auto eqClass : placePartition){
139
auto varMaps = prepareVariables(varModifierMap, &eqClass, postArc, postPlaceId);
146
//Check if the variales on this preArc also appear on other preArcs for the transition
147
//and mark them as diagonal if they do
148
void PartitionBuilder::checkVarOnInputArcs(const std::unordered_map<uint32_t,PositionVariableMap> &placeVariableMap, const PositionVariableMap &preVarPositionMap, std::set<const Colored::Variable*> &diagonalVars, uint32_t placeId){
149
for(const auto &placeVariables : placeVariableMap){
150
for(const auto &variable : preVarPositionMap){
151
for(const auto &varPosition : placeVariables.second){
152
if(varPosition.second == variable.second){
153
diagonalVars.insert(variable.second);
154
if(_partition[placeId].getEquivalenceClasses().back().type()->productSize() == 1){
155
_partition[placeId].setDiagonal(true);
156
} else if(!_partition[placeId].getDiagonalTuplePositions()[variable.first]) {
158
_partition[placeId].setDiagonalTuplePosition(variable.first, true);
161
if(_partition[placeVariables.first].getEquivalenceClasses().back().type()->productSize() == 1){
162
_partition[placeVariables.first].setDiagonal(true);
163
addToQueue(placeVariables.first);
164
} else if(!_partition[placeVariables.first].getDiagonalTuplePositions()[varPosition.first]) {
165
addToQueue(placeVariables.first);
166
_partition[placeVariables.first].setDiagonalTuplePosition(varPosition.first, true);
171
if(_partition[placeId].isDiagonal()){
175
if(_partition[placeId].isDiagonal()){
180
//Check if the preArc share variables with the postArc and mark diagonal if the
181
//variable positions are diagonal in the post place
182
void PartitionBuilder::markSharedVars(const PositionVariableMap &preVarPositionMap, const PositionVariableMap &varPositionMap, uint32_t postPlaceId, uint32_t prePlaceId){
183
for(const auto &preVar : preVarPositionMap){
184
for(const auto &postVar : varPositionMap){
185
if(preVar.second == postVar.second){
186
if(_partition[postPlaceId].isDiagonal() || _partition[postPlaceId].getDiagonalTuplePositions()[postVar.first]){
187
if(_partition[prePlaceId].getEquivalenceClasses().back().type()->productSize() == 1){
188
_partition[prePlaceId].setDiagonal(true);
189
} else if(!_partition[prePlaceId].getDiagonalTuplePositions()[preVar.first]) {
190
addToQueue(prePlaceId);
191
_partition[prePlaceId].setDiagonalTuplePosition(preVar.first, true);
198
//Check if any of the variables on the preArc was part of a diagonal constraint in the gaurd
199
void PartitionBuilder::checkVarInGuard(const PositionVariableMap &preVarPositionMap, const std::set<const Colored::Variable*> &diagonalVars, uint32_t placeId){
200
for(const auto &preVar : preVarPositionMap){
201
if(diagonalVars.count(preVar.second)){
202
if(_partition[placeId].getEquivalenceClasses().back().type()->productSize() == 1){
203
_partition[placeId].setDiagonal(true);
205
} else if(!_partition[placeId].getDiagonalTuplePositions()[preVar.first]) {
207
_partition[placeId].setDiagonalTuplePosition(preVar.first, true);
213
//Check if we have marked all positions in the product type of the place as diagonal
214
//and mark the whole place as diagonal if it is the case
215
bool PartitionBuilder::checkTupleDiagonal(uint32_t placeId){
216
bool allPositionsDiagonal = true;
217
for(auto diag : _partition[placeId].getDiagonalTuplePositions()){
219
allPositionsDiagonal = false;
224
if(allPositionsDiagonal){
225
_partition[placeId].setDiagonal(true);
232
bool PartitionBuilder::checkDiagonal(uint32_t placeId){
233
if(_partition[placeId].isDiagonal()){
240
void PartitionBuilder::applyNewIntervals(const Arc &inArc, const std::vector<PetriEngine::Colored::VariableIntervalMap> &varMaps){
241
//Retrieve the intervals for the current place,
242
//based on the intervals from the postPlace, the postArc, preArc and guard
243
auto outIntervals = inArc.expr->getOutputIntervals(varMaps);
244
EquivalenceVec newEqVec;
245
for(auto& intervalTuple : outIntervals){
246
intervalTuple.simplify();
247
EquivalenceClass newEqClass(++_eq_id_counter, _partition[inArc.place].getEquivalenceClasses().back().type(), std::move(intervalTuple));
248
newEqVec.push_back_Eqclass(std::move(newEqClass));
250
newEqVec.setDiagonalTuplePositions(_partition[inArc.place].getDiagonalTuplePositions());
252
//If the prePlace has not been marked as diagonal, then split the current partitions based on the new intervals
253
if(splitPartition(std::move(newEqVec), inArc.place)){
254
addToQueue(inArc.place);
256
_partition[inArc.place].mergeEqClasses();
259
void PartitionBuilder::handleTransition(const Transition &transition, const uint32_t postPlaceId, const Arc *postArc) {
260
VariableModifierMap varModifierMap;
261
PositionVariableMap varPositionMap;
262
std::set<const PetriEngine::Colored::Variable *> postArcVars;
263
std::set<const PetriEngine::Colored::Variable *> guardVars;
264
std::set<const Colored::Variable*> diagonalVars;
266
postArc->expr->getVariables(postArcVars, varPositionMap, varModifierMap, true);
268
checkVarOnArc(varModifierMap, diagonalVars, postPlaceId, false);
270
if(transition.guard != nullptr){
271
transition.guard->getVariables(guardVars);
273
// we have to copy here, the following loop has the *potential* to modify _partition[postPlaceId]
274
const std::vector<Colored::EquivalenceClass> placePartition = _partition[postPlaceId].getEquivalenceClasses();
276
//Partition each of the equivalence classes
277
for(const auto &eqClass : placePartition){
278
auto varMaps = prepareVariables(varModifierMap, eqClass, postArc, postPlaceId);
280
//If there are variables in the guard, that doesn't come from the postPlace
281
//we give them the full interval
141
282
for(auto& varMap : varMaps){
142
for(auto var : guardVars){
283
for(auto* var : guardVars){
143
284
if(varMap.count(var) == 0){
144
285
varMap[var].addInterval(var->colorType->getFullInterval());
149
if(transition->guard != nullptr){
150
transition->guard->restrictVars(varMaps, diagonalVars);
153
std::unordered_map<uint32_t, std::set<const Colored::Variable *>> placeVariableMap;
154
for(auto inArc : transition->input_arcs){
155
//Hack to avoid considering dot places and dealing with retrieving the correct dot pointer
156
if(_places->operator[](inArc.place).type->getName() == "Dot" || _places->operator[](inArc.place).type->getName() == "dot"){
157
_partition[inArc.place].diagonal = true;
160
if(_partition[inArc.place].diagonal){
164
std::unordered_map<const PetriEngine::Colored::Variable *, std::vector<std::unordered_map<uint32_t, int32_t>>> preVarModifierMap;
165
std::unordered_map<uint32_t, const PetriEngine::Colored::Variable *> preVarPositionMap;
166
std::set<const PetriEngine::Colored::Variable *> preArcVars;
167
inArc.expr->getVariables(preArcVars, preVarPositionMap, preVarModifierMap);
168
for(auto placeVariables : placeVariableMap){
169
for(auto variable : preArcVars){
170
if(placeVariables.second.count(variable)){
171
_partition[inArc.place].diagonal = true;
172
_partition[placeVariables.first].diagonal = true;
173
addToQueue(inArc.place);
174
addToQueue(placeVariables.first);
178
if(_partition[inArc.place].diagonal) {
182
placeVariableMap[inArc.place] = preArcVars;
184
if(_partition[inArc.place].diagonal){
188
if(_partition[postPlaceId].diagonal){
189
for(auto preVar : preArcVars){
190
if(postArcVars.count(preVar)){
191
//maybe something different should happen for tuples
192
// --(x,y)-->[]--(z,y)-->
193
_partition[inArc.place].diagonal = true;
199
if(_partition[inArc.place].diagonal){
200
addToQueue(inArc.place);
204
for(auto varModMap : preVarModifierMap){
205
if(varModMap.second.size() > 1){
206
uint32_t actualSize = 0;
207
for(auto map : varModMap.second){
213
_partition[inArc.place].diagonal = true;
217
for(auto preVar : preArcVars){
218
if(diagonalVars.count(preVar)){
219
//should only happen if the variable is not in a tuple
220
_partition[inArc.place].diagonal = true;
225
auto outIntervals = inArc.expr->getOutputIntervals(varMaps);
226
outIntervals.simplify();
227
EquivalenceVec newEqVec;
228
EquivalenceClass newEqClass = EquivalenceClass(_partition[inArc.place]._equivalenceClasses.back()._colorType, outIntervals);
229
newEqVec._equivalenceClasses.push_back(newEqClass);
231
if((_partition[inArc.place].diagonal || splitPartition(newEqVec, inArc.place))){
232
addToQueue(inArc.place);
237
//is this still needed? does not seem so
238
// std::set<const PetriEngine::Colored::Variable *> preArcVars;
239
// for(auto inArc : transition->input_arcs){
240
// inArc.expr->getVariables(preArcVars);
241
// for(auto postVar : postArcVars){
242
// if(preArcVars.count(postVar)){
243
// if(diagonalVars.count(postVar)){
244
// _partition[inArc.place].diagonal = true;
289
if(transition.guard != nullptr){
290
transition.guard->restrictVars(varMaps, diagonalVars);
293
handleInArcs(transition, diagonalVars, varPositionMap, varMaps, postPlaceId);
297
void PartitionBuilder::handleInArcs(const Transition &transition, std::set<const Colored::Variable*> &diagonalVars, const PositionVariableMap &varPositionMap, const std::vector<PetriEngine::Colored::VariableIntervalMap> &varMaps, uint32_t postPlaceId){
298
std::unordered_map<uint32_t,PositionVariableMap> placeVariableMap;
299
for(const auto &inArc : transition.input_arcs){
300
//Hack to avoid considering dot places
301
if(_places[inArc.place].type == ColorType::dotInstance()){
302
_partition[inArc.place].setDiagonal(true);
305
if(_partition[inArc.place].isDiagonal()){
308
VariableModifierMap preVarModifierMap;
309
PositionVariableMap preVarPositionMap;
310
std::set<const PetriEngine::Colored::Variable *> preArcVars;
311
inArc.expr->getVariables(preArcVars, preVarPositionMap, preVarModifierMap, true);
312
checkVarOnInputArcs(placeVariableMap, preVarPositionMap, diagonalVars, inArc.place);
313
placeVariableMap[inArc.place] = preVarPositionMap;
314
if(checkDiagonal(inArc.place)) continue;
316
markSharedVars(preVarPositionMap, varPositionMap, postPlaceId, inArc.place);
317
if(checkDiagonal(inArc.place)) continue;
318
checkVarOnArc(preVarModifierMap, diagonalVars, inArc.place, true);
319
if(checkDiagonal(inArc.place)) continue;
321
checkVarInGuard(preVarPositionMap, diagonalVars, inArc.place);
322
if(checkDiagonal(inArc.place)) continue;
324
_partition[inArc.place].mergeEqClasses();
325
if(_partition[inArc.place].getEquivalenceClasses().size() >=
326
_partition[inArc.place].getEquivalenceClasses().back().type()->size(_partition[inArc.place].getDiagonalTuplePositions())){
327
_partition[inArc.place].setDiagonal(true);
331
if(checkTupleDiagonal(inArc.place)){
335
applyNewIntervals(inArc, varMaps);
251
339
void PartitionBuilder::addToQueue(uint32_t placeId){
261
349
if(_partition.count(placeId) == 0){
262
350
_partition[placeId] = equivalenceVec;
264
EquivalenceClass intersection = EquivalenceClass();
352
EquivalenceClass intersection(++_eq_id_counter);
265
353
uint32_t ecPos1 = 0, ecPos2 = 0;
266
354
while(findOverlap(equivalenceVec, _partition[placeId],ecPos1, ecPos2, intersection)) {
267
auto ec1 = equivalenceVec._equivalenceClasses[ecPos1];
268
auto ec2 = _partition[placeId]._equivalenceClasses[ecPos2];
269
auto rightSubtractEc = ec1.subtract(ec2, false);
270
auto leftSubtractEc = ec2.subtract(ec1, false);
271
// if((_places->operator[](placeId).name == "NB_ATTENTE_A")) {
272
// std::cout << "comparing " << ec2.toString() << " to " << ec1.toString() << std::endl;
274
// std::cout << "Intersection: " << intersection.toString() << std::endl;
275
// std::cout << "Left: " << leftSubtractEc.toString() << std::endl;
276
// std::cout << "Right: " << rightSubtractEc.toString() << std::endl;
277
// ec2.subtract(ec1, true);
281
equivalenceVec._equivalenceClasses.erase(equivalenceVec._equivalenceClasses.begin() + ecPos1);
282
_partition[placeId]._equivalenceClasses.erase(_partition[placeId]._equivalenceClasses.begin() + ecPos2);
355
const auto &ec1 = equivalenceVec.getEquivalenceClasses()[ecPos1];
356
const auto &ec2 = _partition[placeId].getEquivalenceClasses()[ecPos2];
357
const auto rightSubtractEc = ec1.subtract(++_eq_id_counter, ec2, equivalenceVec.getDiagonalTuplePositions());
358
const auto leftSubtractEc = ec2.subtract(++_eq_id_counter, ec1, _partition[placeId].getDiagonalTuplePositions());
360
equivalenceVec.erase_Eqclass(ecPos1);
361
_partition[placeId].erase_Eqclass(ecPos2);
284
363
if(!intersection.isEmpty()){
285
_partition[placeId]._equivalenceClasses.push_back(intersection);
286
intersection._colorIntervals._intervals.clear();
364
_partition[placeId].push_back_Eqclass(intersection);
365
intersection.clear();
288
367
if(!leftSubtractEc.isEmpty()){
289
_partition[placeId]._equivalenceClasses.push_back(leftSubtractEc);
368
_partition[placeId].push_back_Eqclass(leftSubtractEc);
292
371
if(!rightSubtractEc.isEmpty()){
293
equivalenceVec._equivalenceClasses.push_back(rightSubtractEc);
372
equivalenceVec.push_back_Eqclass(rightSubtractEc);
300
bool PartitionBuilder::findOverlap(EquivalenceVec equivalenceVec1, EquivalenceVec equivalenceVec2, uint32_t &overlap1, uint32_t &overlap2, EquivalenceClass &intersection){
301
for(uint32_t i = 0; i < equivalenceVec1._equivalenceClasses.size(); i++){
302
for(uint32_t j = 0; j < equivalenceVec2._equivalenceClasses.size(); j++){
303
auto ec = equivalenceVec1._equivalenceClasses[i];
304
auto ec2 = equivalenceVec2._equivalenceClasses[j];
379
bool PartitionBuilder::findOverlap(const EquivalenceVec &equivalenceVec1, const EquivalenceVec &equivalenceVec2, uint32_t &overlap1, uint32_t &overlap2, EquivalenceClass &intersection) {
380
for(uint32_t i = 0; i < equivalenceVec1.getEquivalenceClasses().size(); i++){
381
for(uint32_t j = 0; j < equivalenceVec2.getEquivalenceClasses().size(); j++){
382
const auto &ec = equivalenceVec1.getEquivalenceClasses()[i];
383
const auto &ec2 = equivalenceVec2.getEquivalenceClasses()[j];
306
auto intersectingEc = ec.intersect(ec2);
385
auto intersectingEc = ec.intersect(++_eq_id_counter, ec2);
307
386
if(!intersectingEc.isEmpty()){