use of de.hpi.bpt.scylla.model.configuration.ResourceReference in project scylla by bptlab.
the class QueueManager method addToEventQueues.
// public static boolean areResourcesAvailable(SimulationModel model, Set<ResourceReference> resourceReferences,
// String displayName) {
// Map<String, ResourceQueue> resourceObjects = model.getResourceObjects();
// for (ResourceReference resourceRef : resourceReferences) {
// String resourceId = resourceRef.getResourceId();
// int amount = resourceRef.getAmount();
// ResourceQueue queue = resourceObjects.get(resourceId);
// if (queue.size() < amount) {
// model.sendTraceNote("Not enough resources of type " + resourceId + " available, task " + displayName
// + " is put in a queue.");
// return true;
// }
// }
// return false;
// }
/**
* Adds event to event queues.
*
* @param model
* the simulation model
* @param event
* the event to be added to event queues
*/
public static void addToEventQueues(SimulationModel model, ScyllaEvent event) {
ProcessSimulationComponents desmojObjects = event.getDesmojObjects();
int nodeId = event.getNodeId();
Set<ResourceReference> resourceReferences = desmojObjects.getSimulationConfiguration().getResourceReferenceSet(nodeId);
Map<String, ScyllaEventQueue> eventQueues = model.getEventQueues();
for (ResourceReference resourceRef : resourceReferences) {
String resourceId = resourceRef.getResourceId();
ScyllaEventQueue eventQueue = eventQueues.get(resourceId);
eventQueue.offer(event);
}
}
use of de.hpi.bpt.scylla.model.configuration.ResourceReference in project scylla by bptlab.
the class EventOrderPriority method compare.
@Override
public int compare(String resourceId, ScyllaEvent e1, ScyllaEvent e2) throws ScyllaRuntimeException {
SimulationModel model = (SimulationModel) e1.getModel();
if (!model.equals((SimulationModel) e2.getModel())) {
throw new ScyllaRuntimeException("New event for queue is attached to another simulation model.");
}
Integer priorityOfFirstEvent = null;
Set<ResourceReference> resourceRefsOfFirstEvent = e1.getDesmojObjects().getSimulationConfiguration().getResourceReferenceSet(e1.getNodeId());
for (ResourceReference resourceRef : resourceRefsOfFirstEvent) {
if (resourceId.equals(resourceRef.getResourceId())) {
String priorityString = resourceRef.getAssignmentDefinition().get("priority");
if (priorityString == null) {
priorityOfFirstEvent = -1;
} else {
priorityOfFirstEvent = Integer.parseInt(resourceRef.getAssignmentDefinition().get("priority"));
}
}
}
Integer priorityOfSecondEvent = null;
Set<ResourceReference> resourceRefsOfSecondEvent = e2.getDesmojObjects().getSimulationConfiguration().getResourceReferenceSet(e2.getNodeId());
for (ResourceReference resourceRef : resourceRefsOfSecondEvent) {
if (resourceId.equals(resourceRef.getResourceId())) {
String priorityString = resourceRef.getAssignmentDefinition().get("priority");
if (priorityString == null) {
priorityOfSecondEvent = -1;
} else {
priorityOfSecondEvent = Integer.parseInt(resourceRef.getAssignmentDefinition().get("priority"));
}
}
}
// higher value is sorted first
return priorityOfSecondEvent - priorityOfFirstEvent;
}
use of de.hpi.bpt.scylla.model.configuration.ResourceReference in project scylla by bptlab.
the class QueueManager method getResourcesForEvent.
/**
* Returns resource instances which are available for the given event.
*
* @param model
* the simulation model
* @param event
* the DesmoJ event in question
* @return the resource instances which are available for the given event
*/
public static ResourceObjectTuple getResourcesForEvent(SimulationModel model, ScyllaEvent event) {
TimeInstant currentSimulationTime = model.presentTime();
Map<String, List<ResourceObject>> availableResourceObjects = new TreeMap<String, List<ResourceObject>>();
ProcessSimulationComponents desmojObjects = event.getDesmojObjects();
int nodeId = event.getNodeId();
Set<ResourceReference> resourceReferences = desmojObjects.getSimulationConfiguration().getResourceReferenceSet(nodeId);
if (resourceReferences.isEmpty()) {
return new ResourceObjectTuple();
}
Map<String, Integer> resourcesRequired = new HashMap<String, Integer>();
for (ResourceReference ref : resourceReferences) {
String resourceId = ref.getResourceId();
int amount = ref.getAmount();
resourcesRequired.put(resourceId, amount);
}
// keySet() on HashMap returns values on random order
// but we need some fixed order of processing the different resource types
String[] resourceIds = resourcesRequired.keySet().toArray(new String[0]);
// retrieve all available resources
boolean enoughPotentialResourceInstancesAvailable = true;
for (String resourceId : resourceIds) {
int amount = resourcesRequired.get(resourceId);
ResourceQueue queue = model.getResourceObjects().get(resourceId);
List<ResourceObject> resourceObjects = queue.pollAvailable(currentSimulationTime);
availableResourceObjects.put(resourceId, resourceObjects);
if (resourceObjects.size() < amount) {
// less available than required
enoughPotentialResourceInstancesAvailable = false;
break;
}
}
if (!enoughPotentialResourceInstancesAvailable) {
for (String resourceId : availableResourceObjects.keySet()) {
List<ResourceObject> resourceObjects = availableResourceObjects.get(resourceId);
model.getResourceObjects().get(resourceId).addAll(resourceObjects);
}
return null;
}
// find timetable-matching instances per resource -> one match = one tuple
Map<String, List<ResourceObjectTuple>> tuplesPerResource = new HashMap<String, List<ResourceObjectTuple>>();
for (String resourceId : resourceIds) {
int amount = resourcesRequired.get(resourceId);
List<ResourceObject> resourceObjects = availableResourceObjects.get(resourceId);
List<ResourceObjectTuple> tuples = new ArrayList<ResourceObjectTuple>();
for (int index = 0; index < resourceObjects.size(); index++) {
tuples.addAll(findMatchingResourceObjects(resourceObjects, index, amount));
}
tuplesPerResource.put(resourceId, tuples);
}
// match tuples of different resource types
List<ResourceObjectTuple> matchingTuples = findMatchingResourceObjectTuples(tuplesPerResource, resourceIds);
if (matchingTuples.isEmpty()) {
// no resources available
return null;
}
for (ResourceObjectTuple tuple : matchingTuples) {
List<Double> lastAccesses = new ArrayList<Double>();
for (ResourceObject resourceObject : tuple.getResourceObjects()) {
double timeOfLastAccess = resourceObject.getTimeOfLastAccess();
lastAccesses.add(timeOfLastAccess);
}
double avgOfLastAccesses = DateTimeUtils.mean(lastAccesses);
tuple.setAvgOfLastAccesses(avgOfLastAccesses);
}
// sort by average of last access times, ascending (see comparator)
Collections.sort(matchingTuples, resourceObjectTupleComparator);
ResourceObjectTuple chosenTuple = matchingTuples.get(0);
Set<ResourceObject> chosenObjects = chosenTuple.getResourceObjects();
for (String resourceId : availableResourceObjects.keySet()) {
// remove chosen objects from available resource objects
availableResourceObjects.get(resourceId).removeAll(chosenObjects);
// put not-chosen objects back into resource queues
model.getResourceObjects().get(resourceId).addAll(availableResourceObjects.get(resourceId));
}
return chosenTuple;
}
use of de.hpi.bpt.scylla.model.configuration.ResourceReference in project scylla by bptlab.
the class QueueManager method getEventFromQueueReadyForSchedule.
/**
* Returns eventwhich is ready to be scheduled for immediate execution from event queues.
*
* @param model
* the simulation model
* @param resourceQueuesUpdated
* resource queues which have been updated recently -> only the events which require resources from these
* queues are considered
* @return the DesmoJ event which is ready to be scheduled for immediate execution
*/
public static ScyllaEvent getEventFromQueueReadyForSchedule(SimulationModel model, Set<String> resourceQueuesUpdated) {
List<ScyllaEvent> eventCandidates = new ArrayList<ScyllaEvent>();
int accumulatedIndex = Integer.MAX_VALUE;
for (String resourceId : resourceQueuesUpdated) {
ScyllaEventQueue eventQueue = model.getEventQueues().get(resourceId);
for (int i = 0; i < eventQueue.size(); i++) {
ScyllaEvent eventFromQueue = eventQueue.peek(i);
if (eventCandidates.contains(eventFromQueue)) {
continue;
}
int index = 0;
boolean eventIsEligible = hasResourcesForEvent(model, eventFromQueue);
if (eventIsEligible) {
ProcessSimulationComponents desmojObjects = eventFromQueue.getDesmojObjects();
int nodeId = eventFromQueue.getNodeId();
Set<ResourceReference> resourceReferences = desmojObjects.getSimulationConfiguration().getResourceReferenceSet(nodeId);
for (ResourceReference ref : resourceReferences) {
// add position in queue and add to index
String resId = ref.getResourceId();
ScyllaEventQueue eventQ = model.getEventQueues().get(resId);
index += eventQ.getIndex(eventFromQueue);
}
if (accumulatedIndex < index) {
break;
} else if (accumulatedIndex == index) {
eventCandidates.add(eventFromQueue);
} else if (accumulatedIndex > index) {
accumulatedIndex = index;
eventCandidates.clear();
eventCandidates.add(eventFromQueue);
}
}
}
}
if (eventCandidates.isEmpty()) {
return null;
} else {
Collections.sort(eventCandidates, new Comparator<ScyllaEvent>() {
@Override
public int compare(ScyllaEvent e1, ScyllaEvent e2) {
return e1.getSimulationTimeOfSource().compareTo(e2.getSimulationTimeOfSource());
}
});
ScyllaEvent event = eventCandidates.get(0);
// get and assign resources
ResourceObjectTuple resourcesObjectTuple = getResourcesForEvent(model, event);
assignResourcesToEvent(model, event, resourcesObjectTuple);
ProcessSimulationComponents desmojObjects = event.getDesmojObjects();
int nodeId = event.getNodeId();
Set<ResourceReference> resourceReferences = desmojObjects.getSimulationConfiguration().getResourceReferenceSet(nodeId);
for (ResourceReference ref : resourceReferences) {
// remove from event queues
String resourceId = ref.getResourceId();
ScyllaEventQueue eventQueue = model.getEventQueues().get(resourceId);
eventQueue.remove(event);
}
return event;
}
}
use of de.hpi.bpt.scylla.model.configuration.ResourceReference in project scylla by bptlab.
the class SimulationConfigurationParser method parseSimulationConfiguration.
private SimulationConfiguration parseSimulationConfiguration(Element sim, Namespace simNamespace, String processIdFromSimElement, ProcessModel processModel, Long randomSeed) throws ScyllaValidationException {
Map<String, Resource> resources = simulationEnvironment.getGlobalConfiguration().getResources();
if (processModel == null) {
throw new ScyllaValidationException("Simulation configuration is for (sub)process '" + processIdFromSimElement + "', which is not found in the simulation environment.");
}
String processRef = processIdFromSimElement;
String simId = null;
Integer numberOfProcessInstances = null;
ZonedDateTime startDateTime = null;
ZonedDateTime endDateTime = null;
if (processModel.getParent() == null) {
List<Element> startEvents = sim.getChildren("startEvent", simNamespace);
if (startEvents.size() == 0)
throw new ScyllaValidationException("No definition of start event in simulation scenario.");
else {
for (Element el : startEvents) {
// it is sufficient if at least one of the start events has an arrival rate defined
if (el.getChild("arrivalRate", simNamespace) != null) {
break;
}
throw new ScyllaValidationException("No arrival rate defined in any of the start events in simulation scenario.");
}
}
// store identifier of simulation configuration only if it is for top level process
simId = sim.getAttributeValue("id");
numberOfProcessInstances = Integer.valueOf(sim.getAttributeValue("processInstances"));
startDateTime = DateTimeUtils.parse(sim.getAttributeValue("startDateTime"));
String endDateTimeString = sim.getAttributeValue("endDateTime");
if (endDateTimeString != null) {
endDateTime = DateTimeUtils.parse(endDateTimeString);
}
String randomSeedString = sim.getAttributeValue("randomSeed");
if (randomSeedString != null) {
randomSeed = Long.valueOf(sim.getAttributeValue("randomSeed"));
DebugLogger.log("Random seed for simulation configuration " + processRef + ": " + randomSeed);
}
}
Map<Integer, TimeDistributionWrapper> arrivalRates = new HashMap<Integer, TimeDistributionWrapper>();
Map<Integer, TimeDistributionWrapper> durations = new HashMap<Integer, TimeDistributionWrapper>();
Map<Integer, TimeDistributionWrapper> setUpDurations = new HashMap<Integer, TimeDistributionWrapper>();
Map<Integer, Set<ResourceReference>> resourceReferences = new HashMap<Integer, Set<ResourceReference>>();
// gateways and events
// Map<Integer, BranchingBehavior> branchingBehaviors = new HashMap<Integer, BranchingBehavior>();
Map<Integer, SimulationConfiguration> configurationsOfSubProcesses = new HashMap<Integer, SimulationConfiguration>();
// take resource definitions from process model
Map<Integer, Set<String>> resourceReferencesFromProcessModel = processModel.getResourceReferences();
for (Integer nodeId : resourceReferencesFromProcessModel.keySet()) {
Set<String> resourceRefFromModel = resourceReferencesFromProcessModel.get(nodeId);
Set<ResourceReference> resourceRefs = new HashSet<ResourceReference>();
for (String resourceId : resourceRefFromModel) {
int amount = 1;
Map<String, String> assignmentDefinition = new HashMap<String, String>();
ResourceReference resourceReference = new ResourceReference(resourceId, amount, assignmentDefinition);
resourceRefs.add(resourceReference);
}
resourceReferences.put(nodeId, resourceRefs);
}
for (Element el : sim.getChildren()) {
String elementName = el.getName();
if (isKnownElement(elementName)) {
if (elementName.equals("resources")) {
// in parent process
continue;
}
String identifier = el.getAttributeValue("id");
if (identifier == null) {
DebugLogger.log("Warning: Simulation configuration definition element '" + elementName + "' does not have an identifier, skip.");
// no matching element in process, so skip definition
continue;
}
Integer nodeId = processModel.getIdentifiersToNodeIds().get(identifier);
if (nodeId == null) {
DebugLogger.log("Simulation configuration definition for process element '" + identifier + "', but not available in process, skip.");
// no matching element in process, so skip definition
continue;
}
if (elementName.equals("startEvent")) {
Element elem = el.getChild("arrivalRate", simNamespace);
if (elem != null) {
TimeDistributionWrapper distribution = getTimeDistributionWrapper(elem, simNamespace);
arrivalRates.put(nodeId, distribution);
}
} else if (elementName.equals("task") || elementName.endsWith("Task") || elementName.equals("subProcess")) {
Element durationElem = el.getChild("duration", simNamespace);
if (durationElem != null) {
TimeDistributionWrapper distribution = getTimeDistributionWrapper(durationElem, simNamespace);
durations.put(nodeId, distribution);
}
Element setUpDurationElem = el.getChild("setUpDuration", simNamespace);
if (setUpDurationElem != null) {
TimeDistributionWrapper distribution = getTimeDistributionWrapper(setUpDurationElem, simNamespace);
setUpDurations.put(nodeId, distribution);
}
Element resourcesElem = el.getChild("resources", simNamespace);
if (resourcesElem != null) {
List<Element> resourceElements = resourcesElem.getChildren("resource", simNamespace);
// process model)
if (resourceElements.size() > 0) {
Set<ResourceReference> resourceRefs = new HashSet<ResourceReference>();
Set<String> resourceIdentifiers = new HashSet<String>();
for (Element elem : resourceElements) {
String resourceId = elem.getAttributeValue("id");
if (resources.get(resourceId) == null) {
throw new ScyllaValidationException("Simulation configuration " + simId + " refers to unknown resource " + resourceId + ".");
}
if (resourceIdentifiers.contains(resourceId)) {
throw new ScyllaValidationException("Simulation configuration " + simId + " defines multiple resources for task / subprocess " + identifier);
}
resourceIdentifiers.add(resourceId);
// XXX implementation currently supports more than one instance per resource. however
// BPMN standard does not support that.
// int amount = 1;
int amount = Integer.parseInt(elem.getAttributeValue("amount"));
Map<String, String> assignmentDefinition = new HashMap<String, String>();
Element assignmentDefinitionElement = elem.getChild("assignmentDefinition", simNamespace);
if (assignmentDefinitionElement != null) {
List<Element> adElements = assignmentDefinitionElement.getChildren(null, simNamespace);
for (Element adElem : adElements) {
assignmentDefinition.put(adElem.getName(), adElem.getText());
}
}
ResourceReference resourceReference = new ResourceReference(resourceId, amount, assignmentDefinition);
resourceRefs.add(resourceReference);
}
resourceReferences.put(nodeId, resourceRefs);
}
}
if (elementName.equals("subProcess")) {
ProcessModel subProcess = processModel.getSubProcesses().get(nodeId);
String subProcessIdFromSimElement = el.getAttributeValue("id");
SimulationConfiguration simulationConfiguration = parseSimulationConfiguration(el, simNamespace, subProcessIdFromSimElement, subProcess, randomSeed);
configurationsOfSubProcesses.put(nodeId, simulationConfiguration);
}
} else {
DebugLogger.log("Element " + el.getName() + " of simulation scenario is expected to be known, but not supported.");
}
} else {
DebugLogger.log("Element " + el.getName() + " of simulation scenario not supported.");
}
}
SimulationConfiguration simulationConfiguration = new SimulationConfiguration(simId, processModel, numberOfProcessInstances, startDateTime, endDateTime, randomSeed, arrivalRates, durations, setUpDurations, resourceReferences, configurationsOfSubProcesses);
return simulationConfiguration;
}
Aggregations