10 #include "elementary_language.hh"
11 #include "backward_regional_elementary_language.hh"
12 #include "timed_condition_set.hh"
13 #include "juxtaposed_zone_set.hh"
14 #include "renaming_relation.hh"
23 const std::vector<TimedConditionSet> &leftRow,
25 const std::vector<TimedConditionSet> &rightRow,
26 const std::vector<BackwardRegionalElementaryLanguage> &suffixes,
28 #ifdef LEARNTA_DEBUG_EQUIVALENCE
29 BOOST_LOG_TRIVIAL(trace) <<
"left: " << left;
30 BOOST_LOG_TRIVIAL(trace) <<
"right: " << right;
31 BOOST_LOG_TRIVIAL(trace) <<
"leftRowSize: " << leftRow.back().size();
33 BOOST_LOG_TRIVIAL(trace) <<
"rightRowSize: " << rightRow.back().size();
34 BOOST_LOG_TRIVIAL(trace) <<
"suffix.back(): " << suffixes.back();
36 assert(leftRow.size() == rightRow.size());
37 assert(rightRow.size() == suffixes.size());
39 auto juxtaposition = left.getTimedCondition() ^ right.getTimedCondition();
40 juxtaposition.addRenaming(renaming);
41 if (!juxtaposition.isSatisfiableNoCanonize()) {
45 for (std::size_t i = 0; i < leftRow.size(); ++i) {
46 const auto leftConcatenation = left + suffixes.at(i);
47 const auto rightConcatenation = right + suffixes.at(i);
49 rightConcatenation.getTimedCondition(),
50 suffixes.at(i).wordSize()};
54 suffixes.at(i).wordSize()};
56 if (leftJuxtaposition != rightJuxtaposition) {
70 const std::vector<TimedConditionSet> &leftRow,
71 const std::vector<TimedCondition>& leftConcatenation,
73 const std::vector<TimedConditionSet> &rightRow,
74 const std::vector<TimedCondition>& rightConcatenation,
75 const std::vector<BackwardRegionalElementaryLanguage> &suffixes,
77 #ifdef LEARNTA_DEBUG_EQUIVALENCE
78 BOOST_LOG_TRIVIAL(trace) <<
"left: " << left;
79 BOOST_LOG_TRIVIAL(trace) <<
"right: " << right;
80 BOOST_LOG_TRIVIAL(trace) <<
"leftRowSize: " << leftRow.back().size();
82 BOOST_LOG_TRIVIAL(trace) <<
"rightRowSize: " << rightRow.back().size();
83 BOOST_LOG_TRIVIAL(trace) <<
"suffix.back(): " << suffixes.back();
85 assert(leftRow.size() == rightRow.size());
86 assert(rightRow.size() == suffixes.size());
88 auto juxtaposition = left.getTimedCondition() ^ right.getTimedCondition();
89 juxtaposition.addRenaming(renaming);
90 if (!juxtaposition.isSatisfiableNoCanonize()) {
94 for (std::size_t i = 0; i < leftRow.size(); ++i) {
95 JuxtaposedZoneSet leftJuxtaposition{leftRow.at(i), rightConcatenation.at(i), suffixes.at(i).wordSize()};
97 JuxtaposedZoneSet rightJuxtaposition{leftConcatenation.at(i), rightRow.at(i), suffixes.at(i).wordSize()};
99 if (leftJuxtaposition != rightJuxtaposition) {
117 const std::vector<JuxtaposedZoneSet> &leftJuxtapositions,
118 const std::vector<JuxtaposedZoneSet> &rightJuxtapositions,
120 assert(leftJuxtapositions.size() == rightJuxtapositions.size());
123 if (!leftRightJuxtaposition) {
127 return std::equal(leftJuxtapositions.begin(), leftJuxtapositions.end(),
128 rightJuxtapositions.begin(), rightJuxtapositions.end(),
130 left.addRenaming(renaming);
131 right.addRenaming(renaming);
132 return left == right;
136 using RenamingGraph = std::pair<std::vector<std::vector<std::size_t>>, std::vector<std::vector<std::size_t>>>;
150 std::vector<std::vector<std::size_t>> v1Edges, v2Edges;
152 const auto N = left.
size();
153 const auto M = right.
size();
156 std::size_t v1 = 0, v2 = 0;
157 std::vector<std::size_t> currentSameV1, currentSameV2;
158 while (v1 < v1Edges.size() && v2 < v2Edges.size()) {
160 v1Edges.reserve(currentSameV2.size());
161 v2Edges.reserve(currentSameV1.size());
162 std::copy(currentSameV2.begin(), currentSameV2.end(), std::back_inserter(v1Edges.at(v1)));
163 std::for_each(currentSameV2.begin(), currentSameV2.end(), [&](
const auto oldV2) {
164 v2Edges.at(oldV2).push_back(v1);
166 std::copy(currentSameV1.begin(), currentSameV1.end(), std::back_inserter(v2Edges.at(v2)));
167 std::for_each(currentSameV1.begin(), currentSameV1.end(), [&](
const auto oldV1) {
168 v1Edges.at(oldV1).push_back(v2);
170 v1Edges.at(v1).push_back(v2);
171 v2Edges.at(v2).push_back(v1);
172 currentSameV1.push_back(v1);
173 currentSameV2.push_back(v2);
180 currentSameV1.clear();
181 currentSameV2.clear();
191 for (
auto& v1Edge: v1Edges) {
192 std::sort(v1Edge.begin(), v1Edge.end());
193 v1Edge.erase(std::unique(v1Edge.begin(), v1Edge.end()), v1Edge.end());
195 for (
auto& v2Edge: v2Edges) {
196 std::sort(v2Edge.begin(), v2Edge.end());
197 v2Edge.erase(std::unique(v2Edge.begin(), v2Edge.end()), v2Edge.end());
199 return RenamingGraph{v1Edges, v2Edges};
215 const std::vector<std::size_t>& leftConstrained,
216 const std::vector<std::size_t>& rightConstrained,
217 const RenamingGraph& graph) {
221 std::vector<RenamingRelation> candidates;
223 candidates.emplace_back();
224 for (std::size_t j = 0; j < right.
size(); ++j) {
226 if (graph.second.at(j).empty() || right.
getUpperBound(j, right.
size() - 1).second) {
229 std::vector<RenamingRelation> newCandidates;
230 for (
auto candidate: candidates) {
232 if (j > 0 && right.
getUpperBound(j - 1, j - 1) == Bounds{0, true}) {
233 candidate.emplace_back(candidate.back().first, j);
234 newCandidates.emplace_back(std::move(candidate));
238 const std::size_t lowerBound = candidate.empty() ? 0 : (candidate.back().first + 1);
239 const bool constrained = std::binary_search(rightConstrained.begin(), rightConstrained.end(), j);
240 for (
const auto& i: graph.second.at(j)) {
242 if (i >= lowerBound && constrained == std::binary_search(leftConstrained.begin(), leftConstrained.end(), i) &&
243 (i == 0 || left.
getUpperBound(i - 1, i - 1) != Bounds{0, true})) {
244 auto tmpCandidate = candidate;
245 tmpCandidate.emplace_back(i, j);
246 newCandidates.emplace_back(std::move(tmpCandidate));
251 candidates = std::move(newCandidates);
255 candidates.emplace_back();
257 candidates.erase(std::remove_if(candidates.begin(), candidates.end(), [&] (
const auto& renaming) {
258 return renaming.hasImpreciseClocks(right);
259 }), candidates.end());
260 std::sort(candidates.begin(), candidates.end());
261 candidates.erase(std::unique(candidates.begin(), candidates.end()), candidates.end());
287 const auto simpleConcatenations = concatenation.
enumerate();
288 assert((cell.size() == 1 && cell.getConditions().front() == concatenation) ||
289 std::any_of(simpleConcatenations.begin(), simpleConcatenations.end(), [&] (
const TimedCondition& simple) {
290 return std::none_of(cell.getConditions().begin(), cell.getConditions().end(),
291 [&] (const TimedCondition& disjunct) {
292 return disjunct.includes(simple);
298 return CellStatus::bottom;
299 }
else if (cell.size() == 1 && cell.getConditions().front() == concatenation) {
300 return CellStatus::top;
302 return CellStatus::middle;
318 static inline std::pair<std::vector<std::size_t>, std::vector<std::size_t>>
320 const std::vector<TimedConditionSet> &rightRow,
321 const std::vector<TimedCondition> &leftConcatenations,
322 const std::vector<TimedCondition> &rightConcatenations,
324 const std::size_t M) {
325 std::vector<std::size_t> constrainedV1, constrainedV2;
326 constrainedV1.reserve(N * leftRow.size());
327 constrainedV2.reserve(M * rightRow.size());
328 for (std::size_t i = 0; i < leftRow.size(); ++i) {
329 auto currentV1Constrained =
330 leftRow.at(i).getStrictlyConstrainedVariables(leftConcatenations.at(i), N);
331 auto currentV2Constrained =
332 rightRow.at(i).getStrictlyConstrainedVariables(rightConcatenations.at(i), M);
333 std::move(currentV1Constrained.begin(), currentV1Constrained.end(), std::back_inserter(constrainedV1));
334 std::move(currentV2Constrained.begin(), currentV2Constrained.end(), std::back_inserter(constrainedV2));
336 std::sort(constrainedV1.begin(), constrainedV1.end());
337 constrainedV1.erase(std::unique(constrainedV1.begin(), constrainedV1.end()), constrainedV1.end());
338 std::sort(constrainedV2.begin(), constrainedV2.end());
339 constrainedV2.erase(std::unique(constrainedV2.begin(), constrainedV2.end()), constrainedV2.end());
344 return std::make_pair(constrainedV1, constrainedV2);
366 const std::vector<TimedConditionSet> &leftRow,
368 const std::vector<TimedConditionSet> &rightRow,
369 const std::vector<BackwardRegionalElementaryLanguage> &suffixes) {
371 assert(leftRow.size() == rightRow.size());
372 assert(rightRow.size() == suffixes.size());
377 if (!std::equal(leftRow.begin(), leftRow.end(), rightRow.begin(), rightRow.end(),
378 [&] (
const auto& leftCell,
const auto& rightCell) {
379 return leftCell.empty() == rightCell.empty();
386 std::vector<TimedCondition> leftConcatenations;
387 leftConcatenations.reserve(suffixes.size());
388 std::transform(suffixes.begin(), suffixes.end(), std::back_inserter(leftConcatenations), [&] (
const auto& suffix) {
389 return left.getTimedCondition() + suffix.getTimedCondition();
392 std::vector<TimedCondition> rightConcatenations;
393 rightConcatenations.reserve(suffixes.size());
394 std::transform(suffixes.begin(), suffixes.end(), std::back_inserter(rightConcatenations), [&] (
const auto& suffix) {
395 return right.getTimedCondition() + suffix.getTimedCondition();
399 std::vector<CellStatus> leftStatus;
400 leftStatus.reserve(suffixes.size());
401 std::transform(leftConcatenations.begin(), leftConcatenations.end(),
402 leftRow.begin(), std::back_inserter(leftStatus),
decideStatus);
403 std::vector<CellStatus> rightStatus;
404 rightStatus.reserve(suffixes.size());
405 std::transform(rightConcatenations.begin(), rightConcatenations.end(),
406 rightRow.begin(), std::back_inserter(rightStatus),
decideStatus);
409 if (!std::equal(leftStatus.begin(), leftStatus.end(), rightStatus.begin(), rightStatus.end())) {
415 right, rightRow, rightConcatenations,
421 const auto graph =
toGraph(left.getTimedCondition(), right.getTimedCondition());
425 leftConcatenations, rightConcatenations,
430 right.getTimedCondition(),
436 const auto leftRightJuxtaposition = left.getTimedCondition() ^ right.getTimedCondition();
438 std::for_each(candidates.begin(), candidates.end(), [&] (
auto &candidate) {
439 if (!candidate.empty()) {
440 candidate.addImplicitConstraints(leftRightJuxtaposition);
443 std::vector<JuxtaposedZoneSet> leftJuxtapositions, rightJuxtapositions;
444 leftJuxtapositions.reserve(leftRow.size());
445 rightJuxtapositions.reserve(rightRow.size());
446 for (std::size_t i = 0; i < leftRow.size(); ++i) {
447 leftJuxtapositions.emplace_back(leftRow.at(i), rightConcatenations.at(i), suffixes.at(i).wordSize());
448 rightJuxtapositions.emplace_back(leftConcatenations.at(i), rightRow.at(i), suffixes.at(i).wordSize());
450 auto it = std::find_if(candidates.begin(), candidates.end(), [&](
const auto &candidate) {
451 return equivalence(leftRightJuxtaposition, leftJuxtapositions, rightJuxtapositions, candidate);
454 if (it != candidates.end()) {
480 const std::vector<TimedConditionSet> &leftRow,
481 const std::vector<TimedCondition>& leftConcatenations,
483 const std::vector<TimedConditionSet> &rightRow,
484 const std::vector<TimedCondition>& rightConcatenations,
485 const std::vector<BackwardRegionalElementaryLanguage> &suffixes) {
487 assert(leftRow.size() == rightRow.size());
488 assert(rightRow.size() == suffixes.size());
493 std::vector<CellStatus> leftStatus;
494 leftStatus.reserve(suffixes.size());
495 std::transform(leftConcatenations.begin(), leftConcatenations.end(),
496 leftRow.begin(), std::back_inserter(leftStatus),
decideStatus);
497 std::vector<CellStatus> rightStatus;
498 rightStatus.reserve(suffixes.size());
499 std::transform(rightConcatenations.begin(), rightConcatenations.end(),
500 rightRow.begin(), std::back_inserter(rightStatus),
decideStatus);
503 if (!std::equal(leftStatus.begin(), leftStatus.end(), rightStatus.begin(), rightStatus.end())) {
509 right, rightRow, rightConcatenations,
515 const auto graph =
toGraph(left.getTimedCondition(), right.getTimedCondition());
519 leftConcatenations, rightConcatenations,
524 right.getTimedCondition(),
530 const auto leftRightJuxtaposition = left.getTimedCondition() ^ right.getTimedCondition();
532 std::for_each(candidates.begin(), candidates.end(), [&] (
auto &candidate) {
533 if (!candidate.empty()) {
534 candidate.addImplicitConstraints(leftRightJuxtaposition);
537 std::vector<JuxtaposedZoneSet> leftJuxtapositions, rightJuxtapositions;
538 leftJuxtapositions.reserve(leftRow.size());
539 rightJuxtapositions.reserve(rightRow.size());
540 for (std::size_t i = 0; i < leftRow.size(); ++i) {
541 leftJuxtapositions.emplace_back(leftRow.at(i), rightConcatenations.at(i), suffixes.at(i).wordSize());
542 rightJuxtapositions.emplace_back(leftConcatenations.at(i), rightRow.at(i), suffixes.at(i).wordSize());
544 auto it = std::find_if(candidates.begin(), candidates.end(), [&](
const auto &candidate) {
545 return equivalence(leftRightJuxtaposition, leftJuxtapositions, rightJuxtapositions, candidate);
548 if (it != candidates.end()) {
579 const std::vector<TimedConditionSet> &leftRow,
581 const std::vector<TimedConditionSet> &rightRow,
582 const std::vector<BackwardRegionalElementaryLanguage> &suffixes) {
584 assert(leftRow.size() == rightRow.size());
585 assert(rightRow.size() == suffixes.size());
595 const auto graph =
toGraph(left.getTimedCondition(), right.getTimedCondition());
596 const auto &v1Edges = graph.first;
597 const auto &v2Edges = graph.second;
599 const auto M = right.
wordSize() + 1;
601 std::vector<TimedCondition> leftConcatenations, rightConcatenations;
602 leftConcatenations.resize(leftRow.size());
603 rightConcatenations.resize(leftRow.size());
605 std::vector<std::size_t> constrainedV1, constrainedV2;
606 for (std::size_t i = 0; i < leftRow.size(); ++i) {
607 leftConcatenations.at(i) = (left + suffixes.at(i)).getTimedCondition();
608 rightConcatenations.at(i) = (right + suffixes.at(i)).getTimedCondition();
610 if (leftRow.at(i).empty() != rightRow.at(i).empty()) {
614 auto currentV1Constrained =
615 leftRow.at(i).getStrictlyConstrainedVariables(leftConcatenations.at(i), N);
616 auto currentV2Constrained =
617 rightRow.at(i).getStrictlyConstrainedVariables(rightConcatenations.at(i), M);
618 std::move(currentV1Constrained.begin(), currentV1Constrained.end(), std::back_inserter(constrainedV1));
619 std::move(currentV2Constrained.begin(), currentV2Constrained.end(), std::back_inserter(constrainedV2));
621 std::sort(constrainedV1.begin(), constrainedV1.end());
622 constrainedV1.erase(std::unique(constrainedV1.begin(), constrainedV1.end()), constrainedV1.end());
624 std::remove_if(constrainedV1.begin(), constrainedV1.end(), [&](
const auto &v1) {
625 return v1Edges.at(v1).empty();
626 }), constrainedV1.end());
627 std::sort(constrainedV2.begin(), constrainedV2.end());
628 constrainedV2.erase(std::unique(constrainedV2.begin(), constrainedV2.end()), constrainedV2.end());
630 std::remove_if(constrainedV2.begin(), constrainedV2.end(), [&](
const auto &v2) {
631 return v2Edges.at(v2).empty();
632 }), constrainedV2.end());
635 std::deque<RenamingRelation> candidates;
636 candidates.emplace_back();
638 std::size_t v1Index = 0, v2Index = 0;
639 while (v1Index < constrainedV1.size() && v2Index < constrainedV2.size()) {
640 std::size_t v1 = constrainedV1.at(v1Index);
641 std::size_t v2 = constrainedV2.at(v2Index);
643 if (v1Edges.at(v1).empty()) {
648 if (v2Edges.at(v2).empty()) {
652 if (!std::binary_search(v1Edges.at(v1).begin(), v1Edges.at(v1).end(), v2)) {
653 if (v1Edges.at(v1).back() >= v2) {
660 if (!std::binary_search(v2Edges.at(v2).begin(), v2Edges.at(v2).end(), v1)) {
661 if (v2Edges.at(v2).back() >= v1) {
668 std::vector<RenamingRelation> tmp;
669 tmp.reserve(candidates.size() * v2Edges.at(v2).size() * v1Edges.at(v1).size());
671 for (
const auto currentV1: v2Edges.at(v2)) {
672 for (
const auto currentV2: v1Edges.at(v1)) {
673 const auto currentEdge = std::make_pair(currentV1, currentV2);
674 for (
const auto &candidate: candidates) {
675 tmp.emplace_back(candidate);
676 tmp.emplace_back(candidate);
677 tmp.back().emplace_back(currentEdge);
679 tmp.back().emplace_back(currentEdge);
684 candidates.resize(tmp.size());
685 std::move(tmp.begin(), tmp.end(), candidates.begin());
687 while (v1Index < constrainedV1.size() && constrainedV1.at(v1Index) <= v2Edges.at(v2).back()) {
690 while (v2Index < constrainedV2.size() && constrainedV2.at(v2Index) <= v1Edges.at(v1).back()) {
697 std::sort(candidates.begin(), candidates.end());
698 candidates.erase(std::unique(candidates.begin(), candidates.end()), candidates.end());
701 const auto leftRightJuxtaposition = left.getTimedCondition() ^ right.getTimedCondition();
703 std::for_each(candidates.begin(), candidates.end(), [&] (
auto &candidate) {
704 if (!candidate.empty()) {
705 candidate.addImplicitConstraints(leftRightJuxtaposition);
708 std::vector<JuxtaposedZoneSet> leftJuxtapositions, rightJuxtapositions;
709 leftJuxtapositions.reserve(leftRow.size());
710 rightJuxtapositions.reserve(leftRow.size());
711 for (std::size_t i = 0; i < leftRow.size(); ++i) {
712 leftJuxtapositions.emplace_back(leftRow.at(i), rightConcatenations.at(i), suffixes.at(i).wordSize());
713 rightJuxtapositions.emplace_back(leftConcatenations.at(i), rightRow.at(i), suffixes.at(i).wordSize());
715 auto it = std::find_if(candidates.begin(), candidates.end(), [&](
const auto &candidate) {
716 return equivalence(leftRightJuxtaposition, leftJuxtapositions, rightJuxtapositions, candidate);
718 if (it == candidates.end()) {
720 while (!candidates.empty()) {
721 const auto candidate = candidates.front();
722 candidates.pop_front();
723 for (
const auto currentV1: constrainedV1) {
724 for (
const auto currentV2: v1Edges.at(currentV1)) {
725 auto newCandidate = candidate;
726 const auto edge = std::make_pair(currentV1, currentV2);
727 auto insertIt = std::lower_bound(newCandidate.begin(), newCandidate.end(), edge);
728 if (insertIt == newCandidate.end() || *insertIt != edge) {
729 newCandidate.insert(insertIt, edge);
730 if (
equivalence(left, leftRow, right, rightRow, suffixes, newCandidate)) {
731 return std::make_optional(newCandidate);
733 candidates.emplace_back(std::move(newCandidate));
741 return std::make_optional(*it);
An elementary language.
Definition: elementary_language.hh:23
bool isSimple() const
Returns if this elementary language is simple.
Definition: elementary_language.hh:66
std::size_t wordSize() const
Returns the number of the events in this elementary language.
Definition: elementary_language.hh:73
Definition: juxtaposed_zone_set.hh:13
void addRenaming(const std::vector< std::pair< std::size_t, std::size_t >> &renaming)
Add renaming constraints.
Definition: juxtaposed_zone_set.hh:58
A zone constructed by juxtaposing two zones with or without shared variables.
Definition: juxtaposed_zone.hh:12
void addRenaming(const std::vector< std::pair< std::size_t, std::size_t >> &renaming)
Add renaming constraints.
Definition: juxtaposed_zone.hh:127
Definition: renaming_relation.hh:16
A set of timed conditions to represent non-convex constraints.
Definition: timed_condition_set.hh:18
A timed condition, a finite conjunction of inequalities of the form , where and .
Definition: timed_condition.hh:19
bool isSimple() const
Returns if this timed condition is simple.
Definition: timed_condition.hh:98
Bounds getUpperBound(std::size_t i, std::size_t j) const
Returns the upper bound of .
Definition: timed_condition.hh:232
size_t size() const
Return the number of the variables in this timed condition.
Definition: timed_condition.hh:89
void enumerate(std::vector< TimedCondition > &simpleConditions) const
Make a vector of simple timed conditions in this timed condition.
Definition: timed_condition.hh:299
Definition: experiment_runner.hh:23
bool is_strict_ascending(const std::vector< T > &container)
Check if the elements are sorted in the strict ascending order.
Definition: common_types.hh:54
CellStatus
The status of a cell of the observation table.
Definition: equivalence.hh:273
static std::optional< RenamingRelation > findDeterministicEquivalentRenaming(const ElementaryLanguage &left, const std::vector< TimedConditionSet > &leftRow, const std::vector< TimedCondition > &leftConcatenations, const ElementaryLanguage &right, const std::vector< TimedConditionSet > &rightRow, const std::vector< TimedCondition > &rightConcatenations, const std::vector< BackwardRegionalElementaryLanguage > &suffixes)
Return a renaming constraint if two elementary languages are equivalent.
Definition: equivalence.hh:479
static RenamingGraph toGraph(const TimedCondition &left, const TimedCondition &right)
Construct the intermediate bipartite graph for candidate generation from timed conditions.
Definition: equivalence.hh:146
static std::vector< RenamingRelation > generateDeterministicCandidates(const TimedCondition &left, const TimedCondition &right, const std::vector< std::size_t > &leftConstrained, const std::vector< std::size_t > &rightConstrained, const RenamingGraph &graph)
Construct candidate renaming relations that are deterministic, i.e., the corresponding reset only mak...
Definition: equivalence.hh:213
static bool equivalence(JuxtaposedZone leftRightJuxtaposition, const std::vector< JuxtaposedZoneSet > &leftJuxtapositions, const std::vector< JuxtaposedZoneSet > &rightJuxtapositions, const RenamingRelation &renaming)
Return if two elementary languages are equivalent.
Definition: equivalence.hh:116
static std::optional< RenamingRelation > findEquivalentRenaming(const ElementaryLanguage &left, const std::vector< TimedConditionSet > &leftRow, const ElementaryLanguage &right, const std::vector< TimedConditionSet > &rightRow, const std::vector< BackwardRegionalElementaryLanguage > &suffixes)
Construct a renaming constraint if two elementary languages are equivalent.
Definition: equivalence.hh:578
static CellStatus decideStatus(const TimedCondition &concatenation, const TimedConditionSet &cell)
Compute the status of a cell of the observation table.
Definition: equivalence.hh:284
static bool equivalence(const ElementaryLanguage &left, const std::vector< TimedConditionSet > &leftRow, const ElementaryLanguage &right, const std::vector< TimedConditionSet > &rightRow, const std::vector< BackwardRegionalElementaryLanguage > &suffixes, const RenamingRelation &renaming)
Return if two elementary languages are equivalent.
Definition: equivalence.hh:22
static std::pair< std::vector< std::size_t >, std::vector< std::size_t > > makeConstrainedVariables(const std::vector< TimedConditionSet > &leftRow, const std::vector< TimedConditionSet > &rightRow, const std::vector< TimedCondition > &leftConcatenations, const std::vector< TimedCondition > &rightConcatenations, const std::size_t N, const std::size_t M)
Return the constrained variables in the symbolic membership.
Definition: equivalence.hh:319