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 { enabledTransitions.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++) { marking.addAll(Collections.nCopies(places[p].tokens, p)); } return marking.toArray(new Integer[0]); } }