/** * Avoids creating a generic array, which is converted back to list in CompositeCollection. */ private <T extends TMObjectIF> CompositeCollection<T> createComposite(Collection<Collection<T>> collections) { CompositeCollection<T> result = new CompositeCollection<>(); for (Collection<T> collection : collections) { result.addComposited(collection); } return result; }
/** * Add the necessary constraints to produce an equal-conflict (EC) Petri net. A Petri net is EC if is * homogeneous (all transitions consuming tokens from a place do so with the same weight) and transitions with * non-disjoint presets have the same preset. * @param utility The region utility. * @param backwardWeight Terms representing the backwards weights of transitions. * @return The needed terms. */ private List<Term> requireEqualConflict(RegionUtility utility, Term[] backwardWeight) { if (backwardWeight.length == 0) return Collections.emptyList(); TransitionSystem ts = utility.getTransitionSystem(); DomainEquivalenceRelation<String> relation = new DomainEquivalenceRelation<>(ts.getAlphabet()); // Begin with assuming that all events are equivalent String someEvent = ts.getAlphabet().iterator().next(); for (String otherEvent : ts.getAlphabet()) relation.joinClasses(someEvent, otherEvent); // Then refine this so that in the end only events are equivalent which are always enabled together for (final State state : ts.getNodes()) { relation = relation.refine(new IEquivalenceRelation<String>() { @Override public boolean isEquivalent(String event1, String event2) { Set<State> postset1 = state.getPostsetNodesByLabel(event1); Set<State> postset2 = state.getPostsetNodesByLabel(event2); return postset1.isEmpty() == postset2.isEmpty(); } }); } debug("Enabling-equivalent transitions: ", relation); // The postset of the region must be an equivalence class (or the empty set) List<Term> result = new ArrayList<>(); List<String> eventList = utility.getEventList(); for (Set<String> equivalenceClass : new CompositeCollection<Set<String>>(relation, Collections.singleton(Collections.<String>emptySet()))) { Term[] current = new Term[eventList.size()]; Term pivot = null; for (int index = 0; index < backwardWeight.length; index++) { if (equivalenceClass.contains(utility.getEventList().get(index))) { if (pivot == null) { // The first event in the class must have non-zero backward weight pivot = backwardWeight[index]; current[index] = script.term("<", script.numeral(BigInteger.ZERO), pivot); } else { // All other events in the class must have the same weight as pivot current[index] = script.term("=", pivot, backwardWeight[index]); } } else { // Events outside the class must have weight zero current[index] = script.term("=", script.numeral(BigInteger.ZERO), backwardWeight[index]); } } result.add(collectTerms("and", current, script.term("true"))); } return Arrays.asList(collectTerms("or", result.toArray(new Term[0]), script.term("false"))); }