1
package dk.aau.cs.model.tapn;
3
import java.math.BigDecimal;
4
import java.util.ArrayList;
5
import java.util.HashMap;
7
import java.util.Map.Entry;
9
import dk.aau.cs.model.tapn.simulation.FiringMode;
10
import dk.aau.cs.util.Require;
12
public class NetworkMarking implements TimedMarking {
13
private HashMap<TimedArcPetriNet, LocalTimedMarking> markings = new HashMap<TimedArcPetriNet, LocalTimedMarking>();
14
private HashMap<TimedPlace, List<TimedToken>> sharedPlacesTokens = new HashMap<TimedPlace, List<TimedToken>>();
16
public NetworkMarking() {
19
public void addMarking(TimedArcPetriNet tapn, LocalTimedMarking marking) {
20
Require.that(tapn != null, "tapn must not be null");
21
Require.that(!markings.containsKey(tapn), "There is already a marking for that tapn");
23
marking.setNetworkMarking(this);
24
markings.put(tapn, marking);
27
public void removeMarkingFor(TimedArcPetriNet tapn) {
28
Require.that(tapn != null, "tapn must be non-null");
30
if (markings.containsKey(tapn)){
31
LocalTimedMarking marking = markings.remove(tapn);
32
marking.setNetworkMarking(null);
36
private LocalTimedMarking getMarkingFor(TimedArcPetriNet tapn) {
37
return markings.get(tapn);
40
public NetworkMarking clone() {
41
return delay(BigDecimal.ZERO);
44
// private NetworkMarking shallowCopy() {
45
// NetworkMarking shallowCopy = new NetworkMarking();
47
// for (Entry<TimedArcPetriNet, LocalTimedMarking> entry : markings.entrySet()) {
48
// shallowCopy.markings.put(entry.getKey(), entry.getValue());
51
// for(Entry<TimedPlace, List<TimedToken>> entry : sharedPlacesTokens.entrySet()){
52
// shallowCopy.sharedPlacesTokens.put(entry.getKey(), entry.getValue());
55
// return shallowCopy;
58
public boolean isDelayPossible(BigDecimal delay) {
59
for(List<TimedToken> listOfTokens: sharedPlacesTokens.values()){
60
for(TimedToken token : listOfTokens){
61
TimeInvariant invariant = token.place().invariant();
62
if (!invariant.isSatisfied(token.age().add(delay))) {
68
for (LocalTimedMarking marking : markings.values()) {
69
if (!marking.isDelayPossible(delay))
75
public NetworkMarking delay(BigDecimal amount) {
76
Require.that(amount != null, "Delay must not be null");
77
Require.that(isDelayPossible(amount), "Delay breaks invariant.");
79
NetworkMarking newMarking = new NetworkMarking();
80
for(Entry<TimedPlace, List<TimedToken>> entry : sharedPlacesTokens.entrySet()){
81
List<TimedToken> newTokens = new ArrayList<TimedToken>(entry.getValue().size());
82
for(TimedToken token : entry.getValue()){
83
newTokens.add(token.delay(amount));
85
newMarking.sharedPlacesTokens.put(entry.getKey(), newTokens);
88
for (Entry<TimedArcPetriNet, LocalTimedMarking> entry : markings.entrySet()) {
89
newMarking.addMarking(entry.getKey(), entry.getValue().delay(amount));
94
public NetworkMarking fireTransition(TimedTransition transition, FiringMode firingMode) {
95
Require.that(transition != null, "transition cannot be null");
96
Require.that(firingMode != null, "firingMode cannot be null");
98
if(transition.isShared()) return fireSharedTransition(transition.sharedTransition(), firingMode);
100
NetworkMarking clone = clone(); // TODO: try to conserve memory by reusing unchanged markings (they are immutable wrt. transition firing and delay)
101
LocalTimedMarking newMarking = clone.getMarkingFor(transition.model()).fireTransition(transition, firingMode);
103
clone.removeMarkingFor(transition.model());
104
clone.addMarking(transition.model(), newMarking);
109
private NetworkMarking fireSharedTransition(SharedTransition sharedTransition, FiringMode firingMode) {
110
// validity of arguments already checked above
111
NetworkMarking clone = clone();
112
for(TimedTransition transition : sharedTransition.transitions()){
113
LocalTimedMarking ltm = clone.getMarkingFor(transition.model()).fireTransition(transition, firingMode);
115
clone.removeMarkingFor(transition.model());
116
clone.addMarking(transition.model(), ltm);
122
private NetworkMarking fireSharedTransition(SharedTransition sharedTransition, List<TimedToken> tokensToConsume) {
123
HashMap<TimedTransition, List<TimedToken>> tokensPerTransition = distributeTokensToIndividualTransitions(sharedTransition, tokensToConsume);
125
NetworkMarking clone = clone();
126
for(TimedTransition transition : sharedTransition.transitions()){
127
LocalTimedMarking ltm = clone.getMarkingFor(transition.model()).fireTransition(transition, tokensPerTransition.get(transition));
129
clone.removeMarkingFor(transition.model());
130
clone.addMarking(transition.model(), ltm);
136
private HashMap<TimedTransition, List<TimedToken>> distributeTokensToIndividualTransitions(SharedTransition sharedTransition, List<TimedToken> tokensToConsume) {
137
HashMap<TimedTransition, List<TimedToken>> distributedTokens = new HashMap<TimedTransition, List<TimedToken>>();
139
for(TimedToken token : tokensToConsume){
140
for(TimedTransition transition : sharedTransition.transitions()){
141
if(!distributedTokens.containsKey(transition)) distributedTokens.put(transition, new ArrayList<TimedToken>());
143
if(transition.model().equals(((LocalTimedPlace)token.place()).model())){
144
distributedTokens.get(transition).add(token);
150
return distributedTokens;
153
public NetworkMarking fireTransition(TimedTransition transition, List<TimedToken> tokensToConsume) {
154
Require.that(transition != null, "transition cannot be null");
155
Require.that(tokensToConsume != null, "Must specify a list of tokens");
157
if(transition.isShared()) return fireSharedTransition(transition.sharedTransition(), tokensToConsume);
159
NetworkMarking clone = clone(); // TODO: Try to conserve memory by reusing unchanged markings (they are immutable wrt. transition firing and delay)
160
// cannot be done right now because the fireTransition call on local marking needs the reference setup properly to the new network marking
161
LocalTimedMarking newMarking = clone.getMarkingFor(transition.model()).fireTransition(transition, tokensToConsume);
163
clone.removeMarkingFor(transition.model());
164
clone.addMarking(transition.model(), newMarking);
172
for (LocalTimedMarking marking : markings.values()) {
173
size += marking.size();
176
for(List<TimedToken> tokens : sharedPlacesTokens.values()){
177
size += tokens.size();
182
public void add(TimedToken token) {
183
if(token.place().isShared()){
184
addTokenToSharedPlace(token);
186
getMarkingFor(((LocalTimedPlace)token.place()).model()).add(token); // TODO: ugly cast, but only way to get model?
190
private void addTokenToSharedPlace(TimedToken token) {
191
Require.that(token.place().isShared(), "Token must be located in a shared place");
192
if(!sharedPlacesTokens.containsKey(token.place())){
193
sharedPlacesTokens.put(token.place(), new ArrayList<TimedToken>());
196
sharedPlacesTokens.get(token.place()).add(token);
199
public List<TimedToken> getTokensFor(TimedPlace place){
200
if(place.isShared()){
201
if(!sharedPlacesTokens.containsKey(place)) return new ArrayList<TimedToken>();
202
return sharedPlacesTokens.get(place);
204
LocalTimedPlace timedPlace = (LocalTimedPlace)place;
205
return getMarkingFor(timedPlace.model()).getTokensFor(timedPlace);
209
public void remove(TimedToken token) {
210
TimedPlace place = token.place();
211
if(place.isShared()){
212
if(sharedPlacesTokens.containsKey(place)){
213
sharedPlacesTokens.get(place).remove(token);
216
getMarkingFor(((LocalTimedPlace)place).model()).remove(token); // TODO: this is ugly but only way to obtain the model?
220
public void removePlaceFromMarking(TimedPlace place) {
221
if(place.isShared()){
222
if(sharedPlacesTokens.containsKey(place)){
223
sharedPlacesTokens.remove(place);
226
getMarkingFor(((LocalTimedPlace)place).model()).removePlaceFromMarking(place);