private void stepComplete(KpSimulationStep step)
 {
     owt.WriteLine();
     owt.WriteLine("Configuration #{0}", step.Step);
     owt.WriteLine("-------------------------------------------------");
     writeKPsystem(step.KPsystem);
     owt.WriteLine("-------------------------------------------------");
 }
Exemplo n.º 2
0
        public KPsystem Run()
        {
            KpSimulationStep simStep = new KpSimulationStep()
            {
                KPsystem = kp, Step = step
            };

            if (SimulationStarted != null)
            {
                SimulationStarted(kp);
            }

            List <ActiveInstance>    activeInstances  = new List <ActiveInstance>();
            List <ActiveInstance>    targetSelections = new List <ActiveInstance>();
            HashSet <ActiveInstance> deadCells        = new HashSet <ActiveInstance>();

            while (!isHalted && step <= endStep)
            {
                rulesApplied = 0;
                bool advanceStrategyBlock = false;
                bool endStepForInstance   = false;

                bool dissolutionRuleApplied = false;
                bool divisionRuleApplied    = false;
                bool linkRuleApplied        = false;

                activeInstances.AddRange(allOperationalInstances);
                int aiCount = activeInstances.Count;

                while (aiCount > 0)
                {
                    //reset instance flags
                    advanceStrategyBlock = false;
                    endStepForInstance   = false;

                    //select an instance
                    ActiveInstance selectedInstance = activeInstances[rand.Next(aiCount)];

                    ExecutionStrategy ex = selectedInstance.CurrentStrategySegment;

                    //this can only happen if the rule set was set to empty
                    if (selectedInstance.ApplicableRules.Count > 0)
                    {
                        Rule selectedRule     = null;
                        bool isRuleApplicable = true;
                        if (ex.Operator == StrategyOperator.SEQUENCE)
                        {
                            selectedRule = selectedInstance.ApplicableRules.First();
                            if (selectedRule.IsGuarded)
                            {
                                if (!selectedRule.Guard.IsSatisfiedBy(selectedInstance.Instance.Multiset))
                                {
                                    isRuleApplicable = false;
                                }
                                else if (selectedInstance.FlagStructureRuleApplied)
                                {
                                    if (selectedRule.IsStructureChangingRule())
                                    {
                                        isRuleApplicable = false;
                                    }
                                }
                            }
                        }
                        else
                        {
                            int selectedIndex = 0;
                            int arCount       = selectedInstance.ApplicableRules.Count;

                            if (ex.Operator == StrategyOperator.ARBITRARY)
                            {
                                selectedIndex = rand.Next(arCount + 1);
                            }
                            else
                            {
                                selectedIndex = rand.Next(arCount);
                            }

                            if (selectedIndex == arCount)
                            {
                                //this essentially means "skip this block" - always in an arbitrary block, never elsewhere
                                selectedRule     = null;
                                isRuleApplicable = false;
                            }
                            else
                            {
                                selectedRule = selectedInstance.ApplicableRules[selectedIndex];
                                if (selectedInstance.FlagStructureRuleApplied)
                                {
                                    if (selectedRule.IsStructureChangingRule())
                                    {
                                        isRuleApplicable = false;
                                    }
                                }
                            }
                        }

                        if (isRuleApplicable)
                        {
                            if (selectedRule is ConsumerRule)
                            {
                                if ((selectedRule as ConsumerRule).Lhs > selectedInstance.Instance.Multiset)
                                {
                                    isRuleApplicable = false;
                                }
                            }
                        }

                        //At this point, the isRuleApplicable basically confirms that no structure rule has been applied thus far
                        //if the selected rule requires this, if guarded, the guard of the selected rule holds and
                        //the left hand multiset is contained in the instance multiset
                        if (isRuleApplicable)
                        {
                            switch (selectedRule.Type)
                            {
                            case RuleType.REWRITE_COMMUNICATION: {
                                RewriteCommunicationRule rcr = selectedRule as RewriteCommunicationRule;
                                foreach (KeyValuePair <IInstanceIdentifier, TargetedMultiset> kv in rcr.TargetRhs)
                                {
                                    if (kv.Key is InstanceIdentifier)
                                    {
                                        InstanceIdentifier iid = kv.Key as InstanceIdentifier;
                                        if (iid.Indicator == InstanceIndicator.TYPE)
                                        {
                                            IndexedMType targetType = indexedTypesByName[iid.Value];
                                            int          cCount     = selectedInstance.ConnectionCount(targetType);
                                            if (cCount > 0)
                                            {
                                                ActiveInstance selectedTarget = selectedInstance.GetTargetAtIndex(rand.Next(cCount), targetType);
                                                selectedTarget.CommunicatedMultiset = kv.Value.Multiset;
                                                targetSelections.Add(selectedTarget);
                                            }
                                            else
                                            {
                                                isRuleApplicable = false;
                                                break;
                                            }
                                        }
                                    }
                                }
                                if (isRuleApplicable)
                                {
                                    selectedInstance.Instance.Multiset.Subtract(rcr.Lhs);
                                    selectedInstance.Buffer.Add(rcr.Rhs);
                                    ruleApplied(selectedRule, selectedInstance.Instance);
                                    foreach (ActiveInstance ai in targetSelections)
                                    {
                                        if (step >= startStep)
                                        {
                                            if (recordTargetSelection)
                                            {
                                                if (TargetSelected != null)
                                                {
                                                    TargetSelected(ai.Instance, ai.Type, selectedRule);
                                                }
                                            }
                                        }
                                        ai.CommitCommunication();
                                    }
                                }
                                else
                                {
                                    foreach (ActiveInstance ai in targetSelections)
                                    {
                                        ai.ResetCommunication();
                                    }
                                }
                                targetSelections.Clear();
                            } break;

                            case RuleType.MULTISET_REWRITING: {
                                ruleApplied(selectedRule, selectedInstance.Instance);
                                selectedInstance.Instance.Multiset.Subtract((selectedRule as ConsumerRule).Lhs);
                                selectedInstance.Buffer.Add((selectedRule as RewritingRule).Rhs);
                            } break;

                            case RuleType.MEMBRANE_DISSOLUTION: {
                                ruleApplied(selectedRule, selectedInstance.Instance);
                                dissolutionRuleApplied         = true;
                                selectedInstance.FlagDissolved = true;
                                selectedInstance.Instance.Multiset.Subtract((selectedRule as ConsumerRule).Lhs);
                            } break;

                            case RuleType.LINK_CREATION: {
                                LinkRule lr = selectedRule as LinkRule;
                                if (lr.Target is InstanceIdentifier)
                                {
                                    string         typeName       = (lr.Target as InstanceIdentifier).Value;
                                    IndexedMType   targetType     = indexedTypesByName[typeName];
                                    ActiveInstance selectedTarget = null;
                                    //check if there is a link-free instance we can connect to
                                    int freeLinkCount = targetType.Instances.Count - selectedInstance.ConnectionCount(targetType);
                                    if (freeLinkCount > 0)
                                    {
                                        int selection = rand.Next(freeLinkCount);
                                        int i         = 0;
                                        foreach (ActiveInstance ai in targetType.Instances)
                                        {
                                            if (!selectedInstance.IsConnectedTo(ai))
                                            {
                                                if (i++ == selection)
                                                {
                                                    selectedTarget = ai;
                                                }
                                            }
                                        }

                                        selectedInstance.Instance.Multiset.Subtract(lr.Lhs);
                                        ruleApplied(selectedRule, selectedInstance.Instance);
                                        linkRuleApplied = true;
                                        //selected target can't be null here
                                        selectedInstance.ConnectionToCreate  = selectedTarget;
                                        selectedInstance.FlagLinkRuleApplied = true;
                                        if (step >= startStep)
                                        {
                                            if (recordTargetSelection)
                                            {
                                                if (TargetSelected != null)
                                                {
                                                    TargetSelected(selectedTarget.Instance, selectedTarget.Type, selectedRule);
                                                }
                                            }
                                        }

                                        //a structure rule can only be applied once per step so remove it
                                        selectedInstance.ApplicableRules.Remove(selectedRule);
                                    }
                                    else
                                    {
                                        isRuleApplicable = false;
                                    }
                                }
                            } break;

                            case RuleType.LINK_DESTRUCTION: {
                                LinkRule lr = selectedRule as LinkRule;
                                if (lr.Target is InstanceIdentifier)
                                {
                                    string       typeName   = (lr.Target as InstanceIdentifier).Value;
                                    IndexedMType targetType = indexedTypesByName[typeName];
                                    int          cCount     = selectedInstance.ConnectionCount(targetType);
                                    if (cCount > 0)
                                    {
                                        ActiveInstance selectedTarget = selectedInstance.GetTargetAtIndex(rand.Next(cCount), targetType);

                                        selectedInstance.Instance.Multiset.Subtract(lr.Lhs);
                                        ruleApplied(selectedRule, selectedInstance.Instance);
                                        linkRuleApplied = true;
                                        //selected target can't be null here
                                        selectedInstance.ConnectionToDestroy = selectedTarget;
                                        selectedInstance.FlagLinkRuleApplied = true;
                                        if (step >= startStep)
                                        {
                                            if (recordTargetSelection)
                                            {
                                                if (TargetSelected != null)
                                                {
                                                    TargetSelected(selectedTarget.Instance, selectedTarget.Type, selectedRule);
                                                }
                                            }
                                        }

                                        //a structure rule can only be applied once per step so remove it
                                        selectedInstance.ApplicableRules.Remove(selectedRule);
                                    }
                                    else
                                    {
                                        isRuleApplicable = false;
                                    }
                                }
                            } break;

                            case RuleType.MEMBRANE_DIVISION: {
                                DivisionRule dr = selectedRule as DivisionRule;
                                selectedInstance.Instance.Multiset.Subtract(dr.Lhs);
                                foreach (InstanceBlueprint ib in dr.Rhs)
                                {
                                    selectedInstance.AddInstanceBlueprint(ib, indexedTypesByName[ib.Type.Name]);
                                }
                                selectedInstance.FlagDivided = true;
                                ruleApplied(selectedRule, selectedInstance.Instance);
                                divisionRuleApplied = true;
                            } break;
                            }
                        }


                        if (selectedInstance.FlagDissolved || selectedInstance.FlagDivided)
                        {
                            allOperationalInstances.Remove(selectedInstance);
                            endStepForInstance = true;
                        }
                        else
                        {
                            switch (ex.Operator)
                            {
                            case StrategyOperator.SEQUENCE: {
                                if (isRuleApplicable)
                                {
                                    selectedInstance.ApplicableRules.Remove(selectedRule);
                                }
                                else
                                {
                                    endStepForInstance = true;
                                }
                            } break;

                            case StrategyOperator.MAX: {
                                if (!isRuleApplicable)
                                {
                                    selectedInstance.ApplicableRules.Remove(selectedRule);
                                }
                            } break;

                            case StrategyOperator.CHOICE: {
                                if (isRuleApplicable)
                                {
                                    advanceStrategyBlock = true;
                                }
                                else
                                {
                                    selectedInstance.ApplicableRules.Remove(selectedRule);
                                }
                            } break;

                            case StrategyOperator.ARBITRARY: {
                                if (!isRuleApplicable)
                                {
                                    if (selectedRule == null)
                                    {
                                        advanceStrategyBlock = true;
                                    }
                                    else
                                    {
                                        selectedInstance.ApplicableRules.Remove(selectedRule);
                                    }
                                }
                            } break;
                            }
                        }
                    }

                    if (endStepForInstance)
                    {
                        activeInstances.Remove(selectedInstance);
                    }
                    else
                    {
                        if (selectedInstance.ApplicableRules.Count == 0)
                        {
                            advanceStrategyBlock = true;
                        }

                        if (advanceStrategyBlock)
                        {
                            ex = ex.Next;

                            //if the next execution block is null, then remove this compartment from the active instance array
                            if (ex == null)
                            {
                                activeInstances.Remove(selectedInstance);
                            }
                            else
                            {
                                selectedInstance.CurrentStrategySegment = ex;
                            }
                        }
                    }

                    aiCount = activeInstances.Count;
                }

                if (rulesApplied == 0)
                {
                    isHalted = true;
                }
                else
                {
                    //Clear buffer for all instances;

                    foreach (ActiveInstance instance in allInstances)
                    {
                        instance.CommitBuffer();

                        if (linkRuleApplied)
                        {
                            if (instance.FlagLinkRuleApplied)
                            {
                                instance.CommitConnectionUpdates();
                            }
                        }
                    }

                    if (dissolutionRuleApplied || divisionRuleApplied)
                    {
                        foreach (ActiveInstance instance in allInstances)
                        {
                            if (instance.FlagDissolved)
                            {
                                instance.Instance.IsDissolved = true;
                                deadCells.Add(instance);
                                instance.CommitDissolution();
                            }
                            else if (instance.FlagDivided)
                            {
                                instance.Instance.IsDivided = true;
                                deadCells.Add(instance);
                                instance.CommitNewInstances(onNewInstanceCreated);
                            }
                        }

                        if (divisionRuleApplied)
                        {
                            foreach (ActiveInstance ai in newInstanceSet)
                            {
                                allInstances.Add(ai);
                            }
                            newInstanceSet.Clear();
                        }
                    }

                    foreach (ActiveInstance instance in deadCells)
                    {
                        //remove from allInstances collection such that a dead instance will never be
                        //considered for updates or any sort of operations
                        allInstances.Remove(instance);
                        //remove this instance from the set of instances associated to its type so
                        //it will never be considered for link creation or destruction
                        instance.IndexedMType.Instances.Remove(instance);
                    }

                    if (deadCells.Count > 0)
                    {
                        deadCells.Clear();
                    }

                    //reset execution strategy to begining
                    //it's important this is done after everthing has been commited, because the guards must be evaluated on the updated multiset
                    //in the instance
                    foreach (ActiveInstance ai in allOperationalInstances)
                    {
                        ai.ResetCurrentStrategySegment();
                    }

                    if (step >= startStep)
                    {
                        if (SimulationParams.RecordConfigurations)
                        {
                            if (StepComplete != null)
                            {
                                simStep.Step = step;
                                StepComplete(simStep);
                            }
                        }
                    }
                    ++step;
                }
            }

            --step;
            if (IsHalted() && SystemHalted != null)
            {
                SystemHalted(step);
            }
            if (SimulationComplete != null)
            {
                SimulationComplete(step);
            }

            return(kp);
        }