Search in sources :

Example 1 with ResourceReference

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);
    }
}
Also used : ResourceReference(de.hpi.bpt.scylla.model.configuration.ResourceReference)

Example 2 with ResourceReference

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;
}
Also used : ScyllaRuntimeException(de.hpi.bpt.scylla.exception.ScyllaRuntimeException) ResourceReference(de.hpi.bpt.scylla.model.configuration.ResourceReference) SimulationModel(de.hpi.bpt.scylla.simulation.SimulationModel)

Example 3 with ResourceReference

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;
}
Also used : HashMap(java.util.HashMap) ArrayList(java.util.ArrayList) ArrayList(java.util.ArrayList) List(java.util.List) ResourceReference(de.hpi.bpt.scylla.model.configuration.ResourceReference) TreeMap(java.util.TreeMap) TimeInstant(desmoj.core.simulator.TimeInstant)

Example 4 with ResourceReference

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;
    }
}
Also used : ArrayList(java.util.ArrayList) ScyllaEvent(de.hpi.bpt.scylla.simulation.event.ScyllaEvent) ResourceReference(de.hpi.bpt.scylla.model.configuration.ResourceReference)

Example 5 with ResourceReference

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;
}
Also used : ProcessModel(de.hpi.bpt.scylla.model.process.ProcessModel) HashSet(java.util.HashSet) Set(java.util.Set) HashMap(java.util.HashMap) Element(org.jdom2.Element) ScyllaValidationException(de.hpi.bpt.scylla.exception.ScyllaValidationException) ZonedDateTime(java.time.ZonedDateTime) List(java.util.List) ResourceReference(de.hpi.bpt.scylla.model.configuration.ResourceReference) TimeDistributionWrapper(de.hpi.bpt.scylla.model.configuration.distribution.TimeDistributionWrapper) HashSet(java.util.HashSet) Resource(de.hpi.bpt.scylla.model.global.resource.Resource) SimulationConfiguration(de.hpi.bpt.scylla.model.configuration.SimulationConfiguration) HashMap(java.util.HashMap) Map(java.util.Map)

Aggregations

ResourceReference (de.hpi.bpt.scylla.model.configuration.ResourceReference)5 ArrayList (java.util.ArrayList)2 HashMap (java.util.HashMap)2 List (java.util.List)2 ScyllaRuntimeException (de.hpi.bpt.scylla.exception.ScyllaRuntimeException)1 ScyllaValidationException (de.hpi.bpt.scylla.exception.ScyllaValidationException)1 SimulationConfiguration (de.hpi.bpt.scylla.model.configuration.SimulationConfiguration)1 TimeDistributionWrapper (de.hpi.bpt.scylla.model.configuration.distribution.TimeDistributionWrapper)1 Resource (de.hpi.bpt.scylla.model.global.resource.Resource)1 ProcessModel (de.hpi.bpt.scylla.model.process.ProcessModel)1 SimulationModel (de.hpi.bpt.scylla.simulation.SimulationModel)1 ScyllaEvent (de.hpi.bpt.scylla.simulation.event.ScyllaEvent)1 TimeInstant (desmoj.core.simulator.TimeInstant)1 ZonedDateTime (java.time.ZonedDateTime)1 HashSet (java.util.HashSet)1 Map (java.util.Map)1 Set (java.util.Set)1 TreeMap (java.util.TreeMap)1 Element (org.jdom2.Element)1