From 0c0e347b8cced6146f7203e89e2024525f989407 Mon Sep 17 00:00:00 2001 From: Johannes Mey <johannes.mey@tu-dresden.de> Date: Tue, 23 Jun 2020 15:45:55 +0200 Subject: [PATCH] add p/t net execution (both in-place and by creating new markings) --- src/main/jastadd/Navigation.jrag | 41 +++++++++++++++++++ src/main/jastadd/marking/Execution.jadd | 41 +++++++++++++++++++ src/main/jastadd/marking/Marking.jrag | 21 ++++++++++ src/main/jastadd/marking/Printing.jrag | 11 ++++- .../java/de/tudresden/inf/st/pnml/Main.java | 25 ++++++++++- 5 files changed, 136 insertions(+), 3 deletions(-) create mode 100644 src/main/jastadd/marking/Execution.jadd diff --git a/src/main/jastadd/Navigation.jrag b/src/main/jastadd/Navigation.jrag index 116505e..e84c14f 100644 --- a/src/main/jastadd/Navigation.jrag +++ b/src/main/jastadd/Navigation.jrag @@ -2,6 +2,42 @@ aspect Navigation { inh PetriNet PnObject.petriNet(); eq PetriNet.getChild().petriNet() = this; + java.util.Collection<Place> Transition.incomingPlaces() { + java.util.Set<Place> incomingPlaces = new java.util.HashSet<>(); + for (Arc incomingArc : getInArcList()) { + incomingPlaces.add(incomingArc.getSource().asPlaceNode().place()); + } + return incomingPlaces; + } + + java.util.Collection<Place> Transition.outgoingPlaces() { + java.util.Set<Place> outgoingPlaces = new java.util.HashSet<>(); + for (Arc outgoingArc : getOutArcList()) { + outgoingPlaces.add(outgoingArc.getTarget().asPlaceNode().place()); + } + return outgoingPlaces; + } + + syn boolean Node.isPlaceNode() = false; + eq PlaceNode.isPlaceNode() = true; + + syn PlaceNode Node.asPlaceNode() = null; + eq PlaceNode.asPlaceNode() = this; + + syn boolean Node.isTransitionNode() = false; + eq TransitionNode.isTransitionNode() = true; + + syn TransitionNode Node.asTransitionNode() = null; + eq TransitionNode.asTransitionNode() = this; + + syn Place PlaceNode.place(); + eq Place.place() = this; + eq RefPlace.place() = getRef().place(); + + syn Transition TransitionNode.transition(); + eq Transition.transition() = this; + eq RefTransition.transition() = getRef().transition(); + coll java.util.Set<PnObject> PetriNet.allObjects() [new java.util.HashSet()] root PetriNet; PnObject contributes this to PetriNet.allObjects() @@ -11,4 +47,9 @@ aspect Navigation { Place contributes this to PetriNet.allPlaces() for petriNet(); + + coll java.util.Set<Transition> PetriNet.allTransitions() [new java.util.HashSet()] root PetriNet; + Transition contributes this + to PetriNet.allTransitions() + for petriNet(); } diff --git a/src/main/jastadd/marking/Execution.jadd b/src/main/jastadd/marking/Execution.jadd new file mode 100644 index 0000000..a1b6684 --- /dev/null +++ b/src/main/jastadd/marking/Execution.jadd @@ -0,0 +1,41 @@ +aspect Execution { + + public boolean Marking.fireInPlace() { + return fireInPlace(new Random()); + } + + public boolean Marking.fireInPlace(java.util.Random random) { + return fireInPlace(random, true).isPresent(); + } + + private Optional<Marking> Marking.fireInPlace(java.util.Random random, boolean requireFlush) { + if(enabledTransitions().isEmpty()) return Optional.empty(); + + // select a random transition + Transition transition = enabledTransitions().stream() + .sorted((t1, t2) -> t1.getId().compareTo(t2.getId())) + .skip(random.nextInt(enabledTransitions().size())) + .findFirst().get(); + + // take a token from each incoming place + transition.incomingPlaces().forEach(place -> this.resolvePlace(place).setMarking(this.resolvePlace(place).getMarking()-1)); + + // place a token in each outgoing place + transition.outgoingPlaces().forEach(place -> this.resolvePlace(place).setMarking(this.resolvePlace(place).getMarking()+1)); + + if (requireFlush) { + // flush the entire marking tree + this.flushTreeCache(); + } + + return Optional.of(this); + } + + public Optional<Marking> Marking.fire() { + return fire(new Random()); + } + + public Optional<Marking> Marking.fire(java.util.Random random) { + return treeCopyNoTransform().fireInPlace(random, false); + } +} diff --git a/src/main/jastadd/marking/Marking.jrag b/src/main/jastadd/marking/Marking.jrag index 93a7ec3..c5a365f 100644 --- a/src/main/jastadd/marking/Marking.jrag +++ b/src/main/jastadd/marking/Marking.jrag @@ -24,4 +24,25 @@ aspect Marking { } return map; } + + syn int Marking.marking(Place place) = resolvePlace(place).getMarking(); + + syn boolean Marking.isEnabled(Transition t) { + for (Place place : t.incomingPlaces()) { + if (marking(place) == 0) return false; + } + return true; + } + + syn boolean Marking.isDead() { + for (Transition transition : getPetriNet().allTransitions()) { + if (isEnabled(transition)) return false; + } + return true; + } + + syn java.util.Set<Transition> Marking.enabledTransitions() + = getPetriNet().allTransitions().stream() + .filter(t -> isEnabled(t)) + .collect(Collectors.toSet()); } diff --git a/src/main/jastadd/marking/Printing.jrag b/src/main/jastadd/marking/Printing.jrag index 66bd662..e89c16e 100644 --- a/src/main/jastadd/marking/Printing.jrag +++ b/src/main/jastadd/marking/Printing.jrag @@ -1,10 +1,17 @@ aspect Printing { syn String Marking.print() { StringBuilder b = new StringBuilder(); - b.append("Marking for Petri net '").append(getPetriNet().getId()).append("':\n"); + b.append("Marking for Petri net '").append(getPetriNet().name()).append("':\n"); for (MarkedPlace place : getPlaceList()) { - b.append(" ").append(place.getPlace().getId()).append(": ").append(place.getMarking()).append("\n"); + b.append(" ").append(place.getPlace().name()).append(": ").append(place.getMarking()).append("\n"); + } + b.append("Transitions for Petri net '").append(getPetriNet().name()).append("':\n"); + for (Transition trans : getPetriNet().allTransitions()) { + b.append(" ").append(trans.name()).append(": ").append(isEnabled(trans)?"true":"false").append("\n"); } return b.toString(); } + + syn String PetriNet.name() = hasName()?getName().getText():getId(); + syn String PnObject.name() = hasName()?getName().getText():getId(); } diff --git a/src/main/java/de/tudresden/inf/st/pnml/Main.java b/src/main/java/de/tudresden/inf/st/pnml/Main.java index 25690ef..f1ec059 100644 --- a/src/main/java/de/tudresden/inf/st/pnml/Main.java +++ b/src/main/java/de/tudresden/inf/st/pnml/Main.java @@ -1,5 +1,6 @@ package de.tudresden.inf.st.pnml; +import de.tudresden.inf.st.pnml.jastadd.model.Marking; import de.tudresden.inf.st.pnml.jastadd.model.PetriNet; import fr.lip6.move.pnml.framework.general.PNType; import fr.lip6.move.pnml.framework.hlapi.HLAPIRootClass; @@ -15,6 +16,8 @@ import java.nio.file.Path; import java.nio.file.Paths; import java.util.ArrayList; import java.util.List; +import java.util.Optional; +import java.util.Random; public class Main { @@ -23,11 +26,31 @@ public class Main { public static void main(String[] args) { String fileName = "src/main/resources/minimal.pnml"; +// String fileName = "src/main/resources/philo.pnml"; List<PetriNet> petriNets = parsePnml(fileName); for (PetriNet petriNet : petriNets) { - logger.info(petriNet.initialMarking().print()); + Marking originalMarking = petriNet.initialMarking(); + Marking currentMarking = originalMarking; + logger.info("initial marking:\n{}", originalMarking.print()); + + // always use seed 0, it is the best seed! + Random random1 = new Random(0); + Random random2 = new Random(0); + + for (int i = 1; i <= 5 && !originalMarking.isDead() && !currentMarking.isDead(); i++) { + + Optional<Marking> optionalCurrentMarking = currentMarking.fire(random1); + if (optionalCurrentMarking.isPresent()) { + currentMarking = optionalCurrentMarking.get(); + } else { + throw new RuntimeException("Unable to get successor marking, even though the marking is not dead!"); + } + originalMarking.fireInPlace(random2); + logger.info("Original marking after {} firings: {}", i, originalMarking.print()); + logger.info("Current marking after {} firings: {}", i, currentMarking.print()); + } } } -- GitLab