X-Git-Url: https://develop.uap-core.de/gitweb/petrinet.git/blobdiff_plain/df5d936c9357bec642391c1cd58dd952c67c5e8f..685b0bc0c29700edd27a1ae148b75b417947b8ac:/src/main/java/de/yasc/example/petrinet/Petrinet.java diff --git a/src/main/java/de/yasc/example/petrinet/Petrinet.java b/src/main/java/de/yasc/example/petrinet/Petrinet.java new file mode 100644 index 0000000..f8882f2 --- /dev/null +++ b/src/main/java/de/yasc/example/petrinet/Petrinet.java @@ -0,0 +1,99 @@ +package de.yasc.example.petrinet; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; +import java.util.Random; +import java.util.stream.Collectors; + +public final class Petrinet { + + private static final class Place { + + int tokens; + + boolean empty() { + return tokens <= 0; + } + + void dec() { + assert tokens > 0; + tokens--; + } + + void inc() { + tokens++; + } + } + + private static final class Transition { + + final List preset; + final List postset; + + public Transition(List preset, List postset) { + this.preset = preset; + this.postset = postset; + } + + boolean enabled() { + return preset.stream().noneMatch(Place::empty); + } + + void fire() { + preset.forEach(Place::dec); + postset.forEach(Place::inc); + } + } + + final private Random prng = new Random(); + final private Place[] places; + final private List transitions; + + public Petrinet(int places) { + this.places = new Place[places]; + for (int i = 0 ; i < places ; i++) + this.places[i] = new Place(); + transitions = new ArrayList<>(); + } + + public void addTransistion(Integer[] preset, Integer[] postset) { + transitions.add(new Transition( + Arrays.stream(preset).map((i) -> places[i]).collect(Collectors.toList()), + Arrays.stream(postset).map((i) -> places[i]).collect(Collectors.toList()) + )); + } + + public void addMarking(Integer ... marking) { + Arrays.stream(marking).forEach((i) -> places[i].inc()); + } + + public boolean step() { + var enabledTransitions = transitions.stream().filter(Transition::enabled).collect(Collectors.toList()); + if (enabledTransitions.isEmpty()) { + return false; + } else { + transitions.get(prng.nextInt(enabledTransitions.size())).fire(); + return true; + } + } + + public int step(int k) { + int i = 0; + while (i < k) { + if (!step()) + return i; + ++i; + } + return i; + } + + public Integer[] getMarking() { + final var marking = new ArrayList(); + for (int p = 0 ; p < places.length ; p++) { + Collections.nCopies(places[p].tokens, p).forEach(marking::add); + } + return marking.toArray(new Integer[0]); + } +}