Search in sources :

Example 6 with TimeDistributionWrapper

use of de.hpi.bpt.scylla.model.configuration.distribution.TimeDistributionWrapper in project scylla by bptlab.

the class ProcessSimulationComponents method setSmallestTimeUnit.

private void setSmallestTimeUnit(Map<Integer, TimeDistributionWrapper> durations) {
    for (Integer nodeId : durations.keySet()) {
        TimeDistributionWrapper dist = durations.get(nodeId);
        TimeUnit distTimeUnit = dist.getTimeUnit();
        if (distTimeUnit.ordinal() < model.getSmallestTimeUnit().ordinal()) {
            model.setSmallestTimeUnit(distTimeUnit);
        }
    }
}
Also used : TimeUnit(java.util.concurrent.TimeUnit) TimeDistributionWrapper(de.hpi.bpt.scylla.model.configuration.distribution.TimeDistributionWrapper)

Example 7 with TimeDistributionWrapper

use of de.hpi.bpt.scylla.model.configuration.distribution.TimeDistributionWrapper 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)

Example 8 with TimeDistributionWrapper

use of de.hpi.bpt.scylla.model.configuration.distribution.TimeDistributionWrapper in project scylla by bptlab.

the class BoundarySCParserPlugin method parse.

// Therefore this method should be called just once for a sim.xml file
@Override
public Map<String, Object> parse(SimulationConfiguration simulationInput, Element sim) throws ScyllaValidationException {
    Map<Integer, BranchingBehavior> branchingBehaviors = new HashMap<Integer, BranchingBehavior>();
    Namespace simNamespace = sim.getNamespace();
    ProcessModel processModel = simulationInput.getProcessModel();
    for (Element element : sim.getChildren()) {
        String elementName = element.getName();
        if (elementName.equals("task") || elementName.endsWith("Task") || elementName.equals("subProcess")) {
            String identifier = element.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;
            }
            // Get the list of all corresponding boundary events.
            Element boundaryEventsElem = element.getChild("boundaryEvents", simNamespace);
            if (boundaryEventsElem != null) {
                List<Element> boundaryEventElements = boundaryEventsElem.getChildren("boundaryEvent", simNamespace);
                if (boundaryEventElements.size() > 0) {
                    Map<Integer, Double> probabilities = new HashMap<Integer, Double>();
                    double probabilityOfStandardFlow = 1;
                    for (Element elem : boundaryEventElements) {
                        // Collect probabilities of boundary event occurrence...
                        String id = elem.getAttributeValue("id");
                        Integer nodeIdOfBoundaryEvent = processModel.getIdentifiersToNodeIds().get(id);
                        if (nodeIdOfBoundaryEvent == null) {
                            throw new ScyllaValidationException("Simulation configuration refers to unknown boundary event: " + id);
                        }
                        // ... and subtract them from the default path behavior. The percentage of the default path is just
                        // relevant for interrupting events because its implicit 1 at tasks with only nn-interrupting events.
                        Element eventProbabilityElement = elem.getChild("eventProbability", simNamespace);
                        Double probabilityOfBoundaryEvent = Double.parseDouble(eventProbabilityElement.getText());
                        probabilityOfStandardFlow -= probabilityOfBoundaryEvent;
                        probabilities.put(nodeIdOfBoundaryEvent, probabilityOfBoundaryEvent);
                        // Add the arrival rate (= which is here the time at which the boundary event shall occur) relatively to the start of its task.
                        Element arrivalRateElement = elem.getChild("arrivalRate", simNamespace);
                        if (arrivalRateElement != null) {
                            TimeDistributionWrapper distribution = SimulationConfigurationParser.getTimeDistributionWrapper(arrivalRateElement, simNamespace);
                            // TODO: should be put into an extension attribute
                            simulationInput.getArrivalRates().put(nodeIdOfBoundaryEvent, distribution);
                        }
                    }
                    if (probabilityOfStandardFlow < 0) {
                        // The probability values of boundary events are added why they should not exceed 1 in total.
                        throw new ScyllaValidationException("Simulation configuration defines probabilities for boundary events of task " + identifier + ", exceeding 1 in total.");
                    }
                    /*else if (probabilityOfStandardFlow == 0) { // Does not happen anymore and should not happen semantically correct.
                            DebugLogger
                                    .log("Warning: Simulation configuration defines probabilities for boundary events of task "
                                            + identifier + ", but does not allow the normal flow to fire. \n"
                                            + "This may result in an infinite number of firings of boundary events "
                                            + "if none of them is interrupting.");
                        }*/
                    // XXX timer events do not have probabilities
                    // XXX probability of normal flow is stored under nodeId of task
                    // And save them for now.
                    probabilities.put(nodeId, probabilityOfStandardFlow);
                    BranchingBehavior branchingBehavior = new BranchingBehavior(probabilities);
                    branchingBehaviors.put(nodeId, branchingBehavior);
                }
            }
        }
    }
    // Store all branching behaviors collected for that task.
    HashMap<String, Object> extensionAttributes = new HashMap<String, Object>();
    extensionAttributes.put("branchingBehaviors", branchingBehaviors);
    return extensionAttributes;
}
Also used : ProcessModel(de.hpi.bpt.scylla.model.process.ProcessModel) HashMap(java.util.HashMap) BranchingBehavior(de.hpi.bpt.scylla.model.configuration.BranchingBehavior) Element(org.jdom2.Element) Namespace(org.jdom2.Namespace) ScyllaValidationException(de.hpi.bpt.scylla.exception.ScyllaValidationException) TimeDistributionWrapper(de.hpi.bpt.scylla.model.configuration.distribution.TimeDistributionWrapper)

Aggregations

TimeDistributionWrapper (de.hpi.bpt.scylla.model.configuration.distribution.TimeDistributionWrapper)8 ProcessModel (de.hpi.bpt.scylla.model.process.ProcessModel)5 HashMap (java.util.HashMap)5 TimeUnit (java.util.concurrent.TimeUnit)4 SimulationConfiguration (de.hpi.bpt.scylla.model.configuration.SimulationConfiguration)3 Distribution (de.hpi.bpt.scylla.model.configuration.distribution.Distribution)3 Element (org.jdom2.Element)3 ScyllaValidationException (de.hpi.bpt.scylla.exception.ScyllaValidationException)2 Namespace (org.jdom2.Namespace)2 BranchingBehavior (de.hpi.bpt.scylla.model.configuration.BranchingBehavior)1 ResourceReference (de.hpi.bpt.scylla.model.configuration.ResourceReference)1 BinomialDistribution (de.hpi.bpt.scylla.model.configuration.distribution.BinomialDistribution)1 ConstantDistribution (de.hpi.bpt.scylla.model.configuration.distribution.ConstantDistribution)1 EmpiricalDistribution (de.hpi.bpt.scylla.model.configuration.distribution.EmpiricalDistribution)1 EmpiricalStringDistribution (de.hpi.bpt.scylla.model.configuration.distribution.EmpiricalStringDistribution)1 ErlangDistribution (de.hpi.bpt.scylla.model.configuration.distribution.ErlangDistribution)1 ExponentialDistribution (de.hpi.bpt.scylla.model.configuration.distribution.ExponentialDistribution)1 NormalDistribution (de.hpi.bpt.scylla.model.configuration.distribution.NormalDistribution)1 PoissonDistribution (de.hpi.bpt.scylla.model.configuration.distribution.PoissonDistribution)1 TriangularDistribution (de.hpi.bpt.scylla.model.configuration.distribution.TriangularDistribution)1