/// <summary> /// Determines how many child instances will eventually be generated after running all division rules. For each child /// instance, it generates KPChildInstance (sub class of MInstance) object and adds them as MInstance(regular /// instances) to MType. For each MInstance (including KPChildInstances) an SMV module will be generated. /// </summary> /// <param name="type">KP type (MType)</param> /// <returns>List of child instance of KPChildInstance type</returns> internal static List <KPChildInstance> generateKPChildInstances(MType type) { List <KPChildInstance> kpChildInstances = new List <KPChildInstance>(); //After all divisions, how many child will be generated. int totalChildNumber = 1; ExecutionStrategy eS = type.ExecutionStrategy; while (eS != null) { foreach (var rule in eS.Rules) { if (rule.Type == RuleType.MEMBRANE_DIVISION) { DivisionRule divisionRule = (DivisionRule)rule; totalChildNumber *= divisionRule.Rhs.Count; } } eS = eS.Next; } //for each parent instance, totalChildNumber, child instance will be generated foreach (MInstance kpInstance in type.Instances) { for (int childCount = 1; childCount <= totalChildNumber; childCount++) { KPChildInstance kpChildInstance = new KPChildInstance(kpInstance); kpChildInstance.Order = childCount; kpChildInstance.Name = kpInstance.Name + SMVPreFix.CHILD + childCount; kpChildInstances.Add(kpChildInstance); } } return(kpChildInstances); }
/// <summary> /// It recursively buffers the InstanceBlueprint division rules (in result list) for all child instances, in order to /// get the result of only relevant child, we use childOrderTracer which is kind of the ID of child instance, if the /// recursion arrives this child then performs calculations over buffered @param result. /// </summary> /// <param name="divisionRules"></param> /// <param name="ruleCount"></param> /// <param name="result">Holds list of InstanceBlueprint of division rules</param> private static void getRulePermutation(List <KpCore.Rule> divisionRules, int ruleCount, List <InstanceBlueprint> result) { //if it completes on cycle of recursion if (ruleCount == divisionRules.Count) { //check if this cycle belongs to requested child instance if (childOrderTracer == (kPInstance as KPChildInstance).Order) { //then perform calculation calculateValuesOfDivisionVariables(divisionRules, result); } childOrderTracer++; return; } DivisionRule divisionRule = (DivisionRule)divisionRules.ElementAt(ruleCount); int compartCount = divisionRule.Rhs.Count; ruleCount++; for (int j = 0; j < compartCount; j++) { InstanceBlueprint compartment = divisionRule.Rhs.ElementAt(j); int index = ruleCount - 1; if (result.Count < ruleCount) { result.Insert(index, compartment); } else { result.RemoveAt(index); result.Insert(index, compartment); } getRulePermutation(divisionRules, ruleCount, result); } }
private static void getRulePermutation(ParentInstance parentInstance, List <KpCore.Rule> divisionRules, int ruleCount, List <InstanceBlueprint> result) { if (ruleCount == divisionRules.Count) { formDivisionInstance(parentInstance, divisionRules, result); return; } DivisionRule divisionRule = (DivisionRule)divisionRules.ElementAt(ruleCount); int compartCount = divisionRule.Rhs.Count; ruleCount++; for (int j = 0; j < compartCount; j++) { InstanceBlueprint compartment = divisionRule.Rhs.ElementAt(j); int index = ruleCount - 1; if (result.Count < ruleCount) { result.Insert(index, compartment); } else { result.RemoveAt(index); result.Insert(index, compartment); } getRulePermutation(parentInstance, divisionRules, ruleCount, result); } }
public object VisitRuleRightHandSide(KpLinguaParser.RuleRightHandSideContext context) { var rule = default(ConsumerRule); var ruleMultisetContexts = context.ruleMultiset(); var divisionContexts = context.division(); var dissolutionContext = context.dissolution(); var linkCreationContext = context.linkCreation(); var linkDestructionContext = context.linkDestruction(); if (ruleMultisetContexts != null) { var rewritingRule = default(RewritingRule); if (ruleMultisetContexts.Any(rm => rm.targetedMultiset() != null)) { var rewriteCommunicationRule = new RewriteCommunicationRule(); var targetedMultisets = ruleMultisetContexts.Where(rm => rm.targetedMultiset() != null).Select(rm => rm.targetedMultiset().Accept(this) as TargetedMultiset); rewriteCommunicationRule.AddRhs(targetedMultisets.ToDictionary(tm => tm.Target)); rewritingRule = rewriteCommunicationRule; } else { rewritingRule = new RewritingRule(); } var multisets = ruleMultisetContexts.Where(rm => rm.nonEmptyMultiset() != null).Select(rm => rm.nonEmptyMultiset().Accept(this) as Multiset); foreach (var multiset in multisets) { rewritingRule.AddRhs(multiset); } rule = rewritingRule; } else if (divisionContexts != null) { var divisionRule = new DivisionRule(); foreach (var divisionContext in divisionContexts) { divisionRule.Rhs.Add(divisionContext.Accept(this) as InstanceBlueprint); } rule = divisionRule; } else if (dissolutionContext != null) { rule = dissolutionContext.Accept(this) as DissolutionRule; } else if (linkCreationContext != null) { } else if (linkDestructionContext != null) { } return(rule); }
private static int getTotalAmountOfDivisionVar(IVar variable, List <KpCore.Rule> divisionRules, List <InstanceBlueprint> result) { int totalAmount = 0; bool isFirstParent = true; string typeName = ""; foreach (InstanceBlueprint item in result) { typeName = item.Type.Name; int childValue = 0; int leftValue = 0; foreach (var divisionRule in divisionRules) { DivisionRule divRule = (DivisionRule)divisionRule; if (divRule.Rhs.Contains(item)) { Multiset leftOfRule = divRule.Lhs; foreach (var leftObj in leftOfRule.Objects) { if (leftObj.Equals(variable.Name)) { if (isFirstParent) { totalAmount = leftOfRule[leftObj]; isFirstParent = false; } leftValue = leftOfRule[leftObj]; } } } } Multiset ms = item.Multiset; foreach (var obj in ms.Objects) { if (obj.Equals(variable.Name)) { childValue = ms[obj]; } } totalAmount = totalAmount - leftValue + childValue; } //update max value. if (variable.Type is BoundInt) { (variable.Type as BoundInt).UpperBound = Math.Max((variable.Type as BoundInt).UpperBound, totalAmount); } return(totalAmount); }
private static void buildDivisionVariables(NuSMV.Module module, KPsystem kpSystem, KpCore.MType type, int strategyIndex, KpCore.Rule rule) { DivisionRule divisionRule = (DivisionRule)rule; foreach (var leftHRule in divisionRule.Lhs) { Variable variable = new Variable(leftHRule.Key); if (!module.Variables.Contains(variable)) { variable.Type = new BoundInt(0, setMax(kpSystem, type, module, variable)); variable.Behaviour = VariableBehaviour.REWRITING; variable.Init = setOrUpdateInit(module, variable); module.Variables.Add(variable); } else { //if variable exists then update the upperbound value. variable = (Variable)module.Variables.First(item => item.Name.Equals(leftHRule.Key)); } //add result of rule to caseline BRulesStandardVar.addCaseLineToStandardVariable(variable, rule, module, strategyIndex); } foreach (InstanceBlueprint compartment in divisionRule.Rhs) { MType compType = compartment.Type; if (type.Name.Equals(compType.Name)) { Multiset ms = compartment.Multiset; foreach (var obj in ms.Objects) { Variable variable = new Variable(obj); if (!module.Variables.Contains(variable)) { variable.Type = new BoundInt(0, setMax(kpSystem, compType, module, variable)); variable.Behaviour = VariableBehaviour.DIVISION; variable.Init = setOrUpdateInit(module, variable); module.Variables.Add(variable); } else { variable = (Variable)module.Variables.First(item => item.Name.Equals(obj)); variable.Behaviour = VariableBehaviour.DIVISION; } } } } // add rule to status variable BRulesCustomVar.addRuleToStatusVariable(rule, module, strategyIndex); }
public static string Rule(Rule r) { StringBuilder buf = new StringBuilder(); if (r.IsGuarded) { buf.Append(Guard(r.Guard)).Append(": "); } if (r is ConsumerRule) { buf.Append(Multiset((r as ConsumerRule).Lhs)).Append(" -> "); switch (r.Type) { case RuleType.MULTISET_REWRITING: { buf.Append(Multiset((r as RewritingRule).Rhs)); } break; case RuleType.REWRITE_COMMUNICATION: { RewriteCommunicationRule rcr = r as RewriteCommunicationRule; if (!rcr.Rhs.IsEmpty()) { buf.Append(Multiset(rcr.Rhs)).Append(", "); } int tCount = rcr.TargetRhs.Count; int i = 1; foreach (KeyValuePair <IInstanceIdentifier, TargetedMultiset> kv in rcr.TargetRhs) { if (kv.Key is InstanceIdentifier) { if ((kv.Key as InstanceIdentifier).Indicator == InstanceIndicator.TYPE) { buf.AppendFormat("{{{0}}}({1})", Multiset(kv.Value.Multiset), (kv.Key as InstanceIdentifier).Value); if (i < tCount) { buf.Append(", "); } } } } } break; case RuleType.MEMBRANE_DISSOLUTION: { buf.Append("#"); } break; case RuleType.MEMBRANE_DIVISION: { DivisionRule dr = r as DivisionRule; foreach (InstanceBlueprint ib in dr.Rhs) { buf.AppendFormat("[{0}]({1})", Multiset(ib.Multiset, true), ib.Type.Name); } } break; case RuleType.LINK_CREATION: { LinkRule lr = r as LinkRule; if (lr.Target is InstanceIdentifier) { InstanceIdentifier iid = lr.Target as InstanceIdentifier; if (iid.Indicator == InstanceIndicator.TYPE) { buf.AppendFormat("- ({0})", iid.Value); } } } break; case RuleType.LINK_DESTRUCTION: { LinkRule lr = r as LinkRule; if (lr.Target is InstanceIdentifier) { InstanceIdentifier iid = lr.Target as InstanceIdentifier; if (iid.Indicator == InstanceIndicator.TYPE) { buf.AppendFormat("\\- ({0})", iid.Value); } } } break; } } return(buf.ToString()); }
public static string TranslateRule(Rule r, MType container = null) { StringBuilder buf = new StringBuilder(); if (r is ConsumerRule) { ConsumerRule rule = r as ConsumerRule; if (r.IsGuarded) { buf.Append(TranslateGuard(r.Guard)); buf.Append(": "); } buf.Append(TranslateMultiset(rule.Lhs)); buf.Append(" -> "); switch (r.Type) { case RuleType.MULTISET_REWRITING: { buf.Append(TranslateMultiset((r as RewritingRule).Rhs)); } break; case RuleType.REWRITE_COMMUNICATION: { RewriteCommunicationRule rcr = r as RewriteCommunicationRule; if (!rcr.Rhs.IsEmpty()) { buf.Append(TranslateMultiset(rcr.Rhs)); if (rcr.TargetRhs.Count > 0) { buf.Append(", "); } } buf.Append(TranslateTargetedMultiset(rcr.TargetRhs.Values)); } break; case RuleType.MEMBRANE_DISSOLUTION: { buf.Append("#"); } break; case RuleType.LINK_CREATION: { LinkRule lr = r as LinkRule; if (lr.Target is InstanceIdentifier) { InstanceIdentifier iid = lr.Target as InstanceIdentifier; if (iid.Indicator == InstanceIndicator.TYPE) { buf.Append("-(").Append(iid.Value).Append(")"); } } } break; case RuleType.LINK_DESTRUCTION: { LinkRule lr = r as LinkRule; if (lr.Target is InstanceIdentifier) { InstanceIdentifier iid = lr.Target as InstanceIdentifier; if (iid.Indicator == InstanceIndicator.TYPE) { buf.Append("\\-(").Append(iid.Value).Append(")"); } } } break; case RuleType.MEMBRANE_DIVISION: { DivisionRule dr = r as DivisionRule; foreach (InstanceBlueprint ib in dr.Rhs) { buf.Append("["); if (!ib.Multiset.IsEmpty()) { buf.Append(TranslateMultiset(ib.Multiset)); } buf.Append("]"); if (container != null) { if (container.Name == ib.Type.Name) { continue; } } buf.Append("(").Append(ib.Type.Name).Append(")"); } } break; } buf.Append(" ."); } return buf.ToString(); }
private void writeRule(Rule rule) { owt.Write("{"); bool pItem = writePItem(rule); if (!rule.IsEmpty()) { if (pItem) { owt.Write(", "); } if (rule.IsGuarded) { owt.Write("\"guard\":"); writeGuard(rule.Guard); owt.Write(", "); } if (rule.Type == RuleType.CONSUMER) { owt.Write("\"lhs\":"); writeMultiset((rule as ConsumerRule).Lhs); } else if (rule.Type == RuleType.MULTISET_REWRITING) { RewritingRule r = rule as RewritingRule; owt.Write("\"lhs\":"); writeMultiset(r.Lhs); owt.Write(", \"rhs\":"); writeMultiset(r.Rhs); } else if (rule.Type == RuleType.REWRITE_COMMUNICATION) { RewriteCommunicationRule r = rule as RewriteCommunicationRule; owt.Write("\"lhs\":"); writeMultiset(r.Lhs); owt.Write(", \"rhs\":"); writeMultiset(r.Rhs); owt.Write(", \"targetRhs\":["); int i = 1; foreach (TargetedMultiset tm in r.TargetRhs.Values) { writeTargetedMultiset(tm); if (i++ < r.TargetRhs.Count) { owt.Write(", "); } } owt.Write("]"); } else if (rule.Type == RuleType.MEMBRANE_DIVISION) { DivisionRule r = rule as DivisionRule; owt.Write("\"lhs\":"); writeMultiset(r.Lhs); owt.Write(", \"instances\":["); int i = 1; foreach (InstanceBlueprint ib in r.Rhs) { writeInstanceBlueprint(ib); if (i++ < r.Rhs.Count) { owt.Write(", "); } } owt.Write("]"); } else if (rule.Type == RuleType.LINK_CREATION) { LinkRule r = rule as LinkRule; owt.Write("\"lhs\":"); writeMultiset(r.Lhs); owt.Write(",\"linkCreate\":"); writeInstanceIdentifier(r.Target); } else if (rule.Type == RuleType.LINK_DESTRUCTION) { LinkRule r = rule as LinkRule; owt.Write("\"lhs\":"); writeMultiset(r.Lhs); owt.Write(",\"linkDestroy\":"); writeInstanceIdentifier(r.Target); } else if (rule.Type == RuleType.MEMBRANE_DISSOLUTION) { DissolutionRule r = rule as DissolutionRule; owt.Write("\"lhs\":"); writeMultiset(r.Lhs); owt.Write(", \"dissolve\": true"); } } owt.Write("}"); }
private Rule readRule(XPathNavigator nav) { ConsumerRule rule = null; XPathNavigator rhsNav = nav.SelectSingleNode("rhs"); if (rhsNav != null) { Multiset m = readMultiset(rhsNav); XPathNodeIterator div; if (m.IsEmpty()) { //then we can have structure changing rules div = rhsNav.SelectChildren("instance", String.Empty); if (div.Count > 0) { DivisionRule r = new DivisionRule(); while (div.MoveNext()) { string mtype = div.Current.GetAttribute("mtype", String.Empty); InstanceBlueprint ib = null; if (String.IsNullOrEmpty(mtype)) { ib = new InstanceBlueprint(currentType); } else { ib = new InstanceBlueprint(kp[mtype]); } readMultiset(div.Current, ib.Multiset); r.Rhs.Add(ib); } rule = r; } else { XPathNavigator v; v = rhsNav.SelectSingleNode("linkCreate"); if (v == null) { v = rhsNav.SelectSingleNode("linkDestroy"); if (v == null) { v = rhsNav.SelectSingleNode("dissolve"); if (v != null) { rule = new DissolutionRule(); } } else { rule = LinkRule.LinkDestroy(readInstanceIdentifier(v)); } } else { rule = LinkRule.LinkCreate(readInstanceIdentifier(v)); } } } if (rule == null) { div = rhsNav.SelectChildren("target", String.Empty); if (div.Count > 0) { RewriteCommunicationRule rcr = new RewriteCommunicationRule(); rcr.Rhs.Add(m); while (div.MoveNext()) { TargetedMultiset tm = readTargetedMultiset(div.Current); TargetedMultiset otm = null; rcr.TargetRhs.TryGetValue(tm.Target, out otm); if (otm == null) { rcr.TargetRhs.Add(tm.Target, tm); } else { otm.Multiset.Add(tm.Multiset); } } rule = rcr; } else if (m != null) { rule = new RewritingRule(); (rule as RewritingRule).Rhs.Add(m); } } } if (rule == null) { rule = new ConsumerRule(); } readPItem(nav, rule); rule.Guard = readGuard(nav.SelectSingleNode("guard")); readMultiset(nav.SelectSingleNode("lhs"), rule.Lhs); return(rule); }
internal void build() { int id; MaxLinks = 0; MaxDivisionRate = 0; foreach (MInstance instance in mtype.Instances) { id = nextInstanceId(); MInstanceMeta im = new MInstanceMeta(this, instance, id); iMeta.Add(id, im); kpmm.InstanceRegistry.Add(instance, im); AddSymbols(instance.Multiset.Objects); if (instance.Connections.Count > MaxLinks) { MaxLinks = instance.Connections.Count; } } instances = mtype.Instances.ToArray(); List <Rule> rs = new List <Rule>(); ExecutionStrategy strategy = mtype.ExecutionStrategy; while (strategy != null) { foreach (Rule r in strategy.Rules) { id = nextRuleId(); RuleMeta rm = new RuleMeta(this, r, id); rMeta.Add(id, rm); rs.Add(r); kpmm.RuleRegistry[r] = rm; if (r.IsGuarded) { extractGuardAlphabet(r.Guard); } switch (r.Type) { case RuleType.MULTISET_REWRITING: { AddSymbols((r as RewritingRule).Lhs.Objects); AddSymbols((r as RewritingRule).Rhs.Objects); } break; case RuleType.REWRITE_COMMUNICATION: { RewriteCommunicationRule rc = r as RewriteCommunicationRule; AddSymbols(rc.Lhs.Objects); AddSymbols(rc.Rhs.Objects); foreach (TargetedMultiset tarm in rc.TargetRhs.Values) { if (tarm.Target is InstanceIdentifier) { InstanceIdentifier iId = tarm.Target as InstanceIdentifier; if (iId.Indicator == InstanceIndicator.TYPE) { AddSymbols(tarm.Multiset.Objects, iId.Value); //add interest in this connection interests.Add(kpmm.GetTypeMetaByName(iId.Value, true)); } } } } break; case RuleType.MEMBRANE_DIVISION: { DivisionRule dr = r as DivisionRule; AddSymbols(dr.Lhs.Objects); foreach (InstanceBlueprint ib in dr.Rhs) { AddSymbols(ib.Multiset.Objects, ib.Type.Name); if (ib.Type == MType) { MaxDivisionRate++; divisibleTypes.Add(this); } else { kpmm.GetTypeMetaByName(ib.Type.Name).MaxDivisionRate++; divisibleTypes.Add(kpmm.GetTypeMetaByType(ib.Type)); } } } break; default: { if (r is LinkRule) { LinkRule lr = r as LinkRule; AddSymbols(lr.Lhs.Objects); if (lr.Target is InstanceIdentifier) { InstanceIdentifier iid = lr.Target as InstanceIdentifier; if (iid.Indicator == InstanceIndicator.TYPE) { MTypeMeta mtm = kpmm.GetTypeMetaByName(iid.Value, true); interests.Add(mtm); if (lr.Type == RuleType.LINK_CREATION) { mayConnectTo.Add(mtm); } } } } else if (r is ConsumerRule) { AddSymbols((r as ConsumerRule).Lhs.Objects); } } break; } HasCommunication = HasCommunication || r.Type == RuleType.REWRITE_COMMUNICATION; HasDivision = HasDivision || r.Type == RuleType.MEMBRANE_DIVISION; HasDissolution = HasDissolution || r.Type == RuleType.MEMBRANE_DISSOLUTION; HasLinkCreation = HasLinkCreation || r.Type == RuleType.LINK_CREATION; HasLinkDestruction = HasLinkDestruction || r.Type == RuleType.LINK_DESTRUCTION; } strategy = strategy.Next; } rules = rs.ToArray(); }
/// <summary> /// if variable has NOT been set by XML file then set max automatically /// </summary> /// <param name="kpSystem"></param> /// <param name="myType"></param> /// <param name="module"></param> /// <param name="variable"></param> /// <returns></returns> private static int setMax(KPsystem kpSystem, MType myType, NuSMV.Module module, IVar variable) { int maxVal = 0; foreach (var type in kpSystem.Types) { ExecutionStrategy eS = type.ExecutionStrategy; while (eS != null) { //Inside this type if (myType.Name.Equals(type.Name)) { foreach (var rule in eS.Rules) { //Normal variable if (rule.Type == RuleType.MULTISET_REWRITING) { RewritingRule rwr = (RewritingRule)rule; foreach (var leftHRule in rwr.Lhs) { if (variable.Name.Equals(leftHRule.Key)) { maxVal = Math.Max(maxVal, leftHRule.Value); } } foreach (var rigthHRule in rwr.Rhs) { if (variable.Name.Equals(rigthHRule.Key)) { maxVal = Math.Max(maxVal, rigthHRule.Value); } } } // Communication Var else if (rule.Type == RuleType.REWRITE_COMMUNICATION) { RewriteCommunicationRule rcr = (RewriteCommunicationRule)rule; foreach (var leftHRule in rcr.Lhs) { if (variable.Name.Equals(leftHRule.Key)) { maxVal = Math.Max(maxVal, leftHRule.Value); } } } else if (rule.Type == RuleType.MEMBRANE_DIVISION) { DivisionRule divisionRule = (DivisionRule)rule; foreach (var leftHRule in divisionRule.Lhs) { if (variable.Name.Equals(leftHRule.Key)) { maxVal = Math.Max(maxVal, leftHRule.Value); } } foreach (InstanceBlueprint compartment in divisionRule.Rhs) { MType compType = compartment.Type; if (myType.Name.Equals(compType.Name)) { Multiset ms = compartment.Multiset; foreach (var obj in ms.Objects) { if (variable.Name.Equals(obj)) { maxVal = Math.Max(maxVal, ms[obj]); } } } } } else if (rule.Type == RuleType.MEMBRANE_DISSOLUTION) { DissolutionRule dissolutionRule = (DissolutionRule)rule; foreach (var leftHRule in dissolutionRule.Lhs) { if (variable.Name.Equals(leftHRule.Key)) { maxVal = Math.Max(maxVal, leftHRule.Value); } } } } } //Inside communication rule of other types else { foreach (var rule in eS.Rules) { if (rule.Type == RuleType.REWRITE_COMMUNICATION) { RewriteCommunicationRule rcr = (RewriteCommunicationRule)rule; foreach (var target in rcr.TargetRhs.Values) { TargetedMultiset tg = (TargetedMultiset)target; InstanceIdentifier identifier = (InstanceIdentifier)tg.Target; if (myType.Name.Equals(identifier.Value)) { Multiset ms = tg.Multiset; foreach (var rightVar in ms.Objects) { if (variable.Name.Equals(rightVar)) { maxVal = Math.Max(maxVal, ms[rightVar]); } } } } } else if (rule.Type == RuleType.MEMBRANE_DIVISION) { DivisionRule divisionRule = (DivisionRule)rule; foreach (InstanceBlueprint compartment in divisionRule.Rhs) { MType compType = compartment.Type; if (myType.Name.Equals(compType.Name)) { Multiset ms = compartment.Multiset; foreach (var obj in ms.Objects) { if (variable.Name.Equals(obj)) { maxVal = Math.Max(maxVal, ms[obj]); } } } } } } } eS = eS.Next; } //also compare parameter values foreach (var instance in type.Instances) { foreach (var param in instance.Multiset.Objects) { if (variable.Name.Equals(param)) { maxVal = Math.Max(maxVal, instance.Multiset[param]); } } } } return(maxVal); }
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); }