private static void InterleaveEncodeChannel(List <AutomataBDD> processes, Model model, AutomataBDD result) { for (int i = 0; i < processes.Count; i++) { List <int> unchangedVariableIndex = new List <int>(result.variableIndex); foreach (int index in processes[i].variableIndex) { unchangedVariableIndex.Remove(index); } //Channel communication implicitly is not terminate transition CUDD.Ref(processes[i].channelInTransitionBDD); result.channelInTransitionBDD.AddRange(model.AddVarUnchangedConstraint(processes[i].channelInTransitionBDD, unchangedVariableIndex)); CUDD.Ref(processes[i].prioritychannelIns); result.prioritychannelIns.AddRange(model.AddVarUnchangedConstraint(processes[i].prioritychannelIns, unchangedVariableIndex)); CUDD.Ref(processes[i].channelOutTransitionBDD); result.channelOutTransitionBDD.AddRange(model.AddVarUnchangedConstraint(processes[i].channelOutTransitionBDD, unchangedVariableIndex)); CUDD.Ref(processes[i].prioritychannelOuts); result.prioritychannelOuts.AddRange(model.AddVarUnchangedConstraint(processes[i].prioritychannelOuts, unchangedVariableIndex)); } InterleaveGetChannelTransition(processes, model, result); }
/// <summary> /// Pi.Trans/In/Out ∧ unchanged.i /// unchanged.i :(P.var \ Pi.var) = (P.var \Pi.var) ' /// Still keep the channlInTransitionBDD & channelOutTransitionBDD. when calculate sync channel and add to transition /// [ REFS: '', DEREFS: ''] /// </summary> private static void InterleaveCopyTransition(List <AutomataBDD> processes, Model model, AutomataBDD result) { CUDDNode notTerminateTrans = CUDD.Function.Not(GetTerminationTransEncoding(model)); foreach (var process in processes) { List <int> unchangedVariableIndex = new List <int>(result.variableIndex); foreach (int index in process.variableIndex) { unchangedVariableIndex.Remove(index); } //terminate event is synchornized in interleaving CUDD.Ref(notTerminateTrans); CUDD.Ref(process.transitionBDD); result.transitionBDD.AddRange(model.AddVarUnchangedConstraint(CUDD.Function.And(process.transitionBDD, notTerminateTrans), unchangedVariableIndex)); CUDD.Ref(notTerminateTrans); CUDD.Ref(process.priorityTransitionsBDD); result.priorityTransitionsBDD.AddRange(model.AddVarUnchangedConstraint(CUDD.Function.And(process.priorityTransitionsBDD, notTerminateTrans), unchangedVariableIndex)); } CUDD.Deref(notTerminateTrans); }
/// <summary> /// Tick transition if done is false, don't need to add unchanged condition of other local variables. /// They will be updated after the event becomes true /// use the tick transition of P1 if done is true /// </summary> /// <param name="P1"></param> /// <param name="model"></param> /// <param name="result"></param> private static void EventPrefixEncodeTick(Expression guardOfTick, AutomataBDD P1, Model model, AutomataBDD result) { Expression guard; List<CUDDNode> guardDD; //1. !done and guardOfTick and event = tick and !done' if (!(guardOfTick is BoolConstant && !(guardOfTick as BoolConstant).Value)) { guard = Expression.AND( Expression.EQ( new Variable(result.newLocalVarName), new IntConstant(0)), Expression.AND( guardOfTick, new PrimitiveApplication( PrimitiveApplication.AND, AutomataBDD. GetTerminateTransExpression (), new Assignment( result.newLocalVarName, new IntConstant(0))))); guardDD = guard.TranslateBoolExpToBDD(model).GuardDDs; guardDD = model.AddVarUnchangedConstraint(guardDD, model.GlobalVarIndex); result.Ticks.AddRange(guardDD); } //2. done and p1.Tick and done' guard = Expression.AND(Expression.EQ(new Variable(result.newLocalVarName), new IntConstant(1)), new Assignment(result.newLocalVarName, new IntConstant(0))); guardDD = guard.TranslateBoolExpToBDD(model).GuardDDs; guardDD = CUDD.Function.And(guardDD, P1.Ticks); result.Ticks.AddRange(guardDD); }
/// <summary> /// syncTransition = P1.transition ∧ P2.transition /// syncEvent: formula of synchronized events /// P.transition = syncTransition ∨ (Pi.transition ∧ !syncEvent ∧ unchanged.i) /// Applied this formula for each pair of process: P1 || P2 || P3 = (P1 || P2) || P3 /// [ REFS: '', DEREFS: 'processes[i].transitionBDD, alphabet'] /// </summary> /// <param name="processes"></param> /// <param name="alphabets">alphabet of each process if provided. Give True if not provided</param> /// <param name="model"></param> /// <param name="result"></param> private static void ParallelEncodeTransition(List <AutomataBDD> processes, List <CUDDNode> alphabets, Model model, AutomataBDD result) { List <CUDDNode> transition = processes[0].transitionBDD; CUDDNode lastAlphabet = alphabets[0]; //Do encoding at each step, 2 processes once for (int i = 1; i < processes.Count; i++) { //find sync transitions CUDD.Ref(transition); CUDD.Ref(processes[i].transitionBDD); List <CUDDNode> syncTransition = CUDD.Function.And(transition, processes[i].transitionBDD); //sync alphabet = (P0.alphabet and P1.alphabet) or termination event //We rename the event with assignment whose name may be also in the alphabet //After the rename, they do not belong to the alphabet CUDD.Ref(lastAlphabet, alphabets[i]); CUDDNode syncEvent = CUDD.Function.Or(CUDD.Function.And(lastAlphabet, alphabets[i]), GetTerminationTransEncoding(model)); //sync transition must have no program block which mean no global variable updated foreach (var globalVarIndex in model.GlobalVarIndex) { CUDD.Ref(model.varIdentities[globalVarIndex]); syncEvent = CUDD.Function.And(syncEvent, model.varIdentities[globalVarIndex]); } CUDD.Ref(syncEvent); syncTransition = CUDD.Function.And(syncTransition, syncEvent); //update current alphabet lastAlphabet = CUDD.Function.Or(lastAlphabet, alphabets[i]); CUDD.Ref(syncTransition); List <CUDDNode> tempTransition = new List <CUDDNode>(syncTransition); //find not sync event, we need to add global variable unchanged to syncEvent because for example process a -> a {x = 1} -> P; //a may be in the alphabet, and the first a can be synced, but the secondtion is not CUDDNode notSyncEvents = CUDD.Function.Not(syncEvent); CUDD.Ref(notSyncEvents); tempTransition.AddRange(CUDD.Function.And(transition, notSyncEvents)); tempTransition.AddRange(CUDD.Function.And(processes[i].transitionBDD, notSyncEvents)); transition = tempTransition; } // CUDD.Deref(lastAlphabet); transition = model.AddVarUnchangedConstraint(transition, result.variableIndex); // result.transitionBDD = transition; }
private static void TimeInterruptEncodeTransitionChannel(string clk, AutomataBDD m0, AutomataBDD m1, int t, Model model, AutomataBDD result) { Expression guard; List<CUDDNode> guardDD, transTemp; //1. clk <= t and m0.Trans/In/Out and [(event' = termination & clk' = -1) or (event' != termination & clk' = clk)] guard = Expression.AND(Expression.LE(new Variable(clk), new IntConstant(t)), Expression.OR(Expression.AND( AutomataBDD.GetTerminateTransExpression(), new Assignment(clk, new IntConstant(-1))), Expression.AND( AutomataBDD.GetNotTerminateTransExpression(), new Assignment(clk, new Variable(clk))))); guardDD = guard.TranslateBoolExpToBDD(model).GuardDDs; CUDD.Ref(guardDD); transTemp = CUDD.Function.And(m0.transitionBDD, guardDD); result.transitionBDD.AddRange(transTemp); // CUDD.Ref(guardDD); transTemp = CUDD.Function.And(m0.channelInTransitionBDD, guardDD); result.channelInTransitionBDD.AddRange(transTemp); // //CUDD.Ref(guardDD); transTemp = CUDD.Function.And(m0.channelOutTransitionBDD, guardDD); result.channelOutTransitionBDD.AddRange(transTemp); //2. clk = t and event' = tau and clk' = t + 1 and m1.Init guard = Expression.AND(Expression.EQ(new Variable(clk), new IntConstant(t)), Expression.AND(AutomataBDD.GetTauTransExpression(), new Assignment(clk, new IntConstant(t + 1)))); guardDD = guard.TranslateBoolExpToBDD(model).GuardDDs; guardDD = CUDD.Function.And(m1.GetInitInColumn(model), CUDD.Function.Or(guardDD)); guardDD = model.AddVarUnchangedConstraint(guardDD, model.GlobalVarIndex); result.transitionBDD.AddRange(guardDD); //3. clk = t + 1 and m1.Trans and clk' = t + 1 guard = Expression.AND(Expression.EQ(new Variable(clk), new IntConstant(t + 1)), new Assignment(clk, new IntConstant(t + 1))); guardDD = guard.TranslateBoolExpToBDD(model).GuardDDs; // CUDD.Ref(guardDD); transTemp = CUDD.Function.And(m1.transitionBDD, guardDD); result.transitionBDD.AddRange(guardDD); // CUDD.Ref(guardDD); transTemp = CUDD.Function.And(m1.channelInTransitionBDD, guardDD); result.channelInTransitionBDD.AddRange(guardDD); // //CUDD.Ref(guardDD); transTemp = CUDD.Function.And(m1.channelOutTransitionBDD, guardDD); result.channelOutTransitionBDD.AddRange(guardDD); }
/// <summary> /// Note that this is different from EventPrefixEncodeTick because it need to make sure local variable unchanged /// </summary> /// <param name="P1"></param> /// <param name="model"></param> /// <param name="result"></param> private static void GuardEncodeTick(Expression guard1, AutomataBDD P1, Model model, AutomataBDD result) { //allow time evolution when the guard is not resolved //temp = 0 and P1.init and not (b and P1.init and event = tau and P1.transition) and event = tick and temp = 0 Expression exp; List<CUDDNode> expDD; exp = Expression.AND(guard1, Expression.AND(P1.initExpression, AutomataBDD.GetTauTransExpression())); expDD = exp.TranslateBoolExpToBDD(model).GuardDDs; CUDD.Ref(P1.transitionBDD); expDD = CUDD.Function.And(expDD, P1.transitionBDD); //find state where b is true and tau is enable expDD = CUDD.Abstract.ThereExists(expDD, model.AllColVars); CUDDNode tauIsNotEnabled = CUDD.Function.Not(expDD); exp = Expression.AND( Expression.AND( new PrimitiveApplication( PrimitiveApplication.EQUAL, new Variable(result.newLocalVarName), new IntConstant(0)), P1.initExpression), GetTickTransExpression()); expDD = exp.TranslateBoolExpToBDD(model).GuardDDs; expDD = CUDD.Function.And(expDD, tauIsNotEnabled); expDD = model.AddVarUnchangedConstraint(expDD, model.GlobalVarIndex); expDD = model.AddVarUnchangedConstraint(expDD, result.variableIndex); result.Ticks.AddRange(expDD); //temp & P1.tick & temp' exp = Expression.AND( new Variable(result.newLocalVarName), new Assignment(result.newLocalVarName, new IntConstant(1))); expDD = exp.TranslateBoolExpToBDD(model).GuardDDs; expDD = CUDD.Function.And(P1.Ticks, expDD); result.Ticks.AddRange(expDD); }
private static void SkipEncodeTick(Model model, AutomataBDD result) { //2. state = 0 & event' = tick & state = 0 //3. state = 1 & event' = tick & state = 1 Expression guard = Expression.AND(GetTickTransExpression(), new Assignment(result.newLocalVarName, new Variable(result.newLocalVarName))); List<CUDDNode> guardDD = guard.TranslateBoolExpToBDD(model).GuardDDs; guardDD = model.AddVarUnchangedConstraint(guardDD, model.GlobalVarIndex); result.Ticks.AddRange(guardDD); }
/// <summary> /// Get new Transition from Channel input, channel ouput of sub processes /// [ REFS: '', DEREFS: 'processes.channelInTransitionBDD, channelOutTransitionBDD'] /// </summary> /// <param name="processes"></param> /// <param name="model"></param> /// <param name="result"></param> private static void InterleaveGetChannelTransition(List <AutomataBDD> processes, Model model, AutomataBDD result) { List <CUDDNode> syncedChannelTransition = new List <CUDDNode>(); //Make sure only 2 different processes can join the synchronized channel event for (int i = 0; i < processes.Count; i++) { for (int j = i + 1; j < processes.Count; j++) { if (processes[i].channelInTransitionBDD.Count > 0 && processes[j].channelOutTransitionBDD.Count > 0) { //process i Channel Input, process j Channel Output CUDD.Ref(processes[i].channelInTransitionBDD); CUDD.Ref(processes[j].channelOutTransitionBDD); syncedChannelTransition.AddRange(CUDD.Function.And(processes[i].channelInTransitionBDD, processes[j].channelOutTransitionBDD)); } if (processes[i].channelOutTransitionBDD.Count > 0 && processes[j].channelInTransitionBDD.Count > 0) { //Process i Channel Output, Process j Channel Input CUDD.Ref(processes[i].channelOutTransitionBDD); CUDD.Ref(processes[j].channelInTransitionBDD); syncedChannelTransition.AddRange(CUDD.Function.And(processes[i].channelOutTransitionBDD, processes[j].channelInTransitionBDD)); } } } //Dereference the Channel input, channel output of all sub processes foreach (AutomataBDD process in processes) { CUDD.Deref(process.channelInTransitionBDD, process.channelOutTransitionBDD); } //2 processes join in the channel sycchronized event, other must be unchanged syncedChannelTransition = model.AddVarUnchangedConstraint(syncedChannelTransition, result.variableIndex); syncedChannelTransition = model.AddVarUnchangedConstraint(syncedChannelTransition, model.GlobalVarIndex); // if (syncedChannelTransition.Count > 0) { result.transitionBDD.Add(CUDD.Function.Or(syncedChannelTransition)); } }
/// <summary> /// Return AutomataBDD of Stop process /// </summary> /// <returns></returns> public static AutomataBDD Stop(Model model) { AutomataBDD result = new AutomataBDD(); Expression guard = GetTickTransExpression(); List<CUDDNode> guardDD = guard.TranslateBoolExpToBDD(model).GuardDDs; guardDD = model.AddVarUnchangedConstraint(guardDD, model.GlobalVarIndex); result.Ticks.AddRange(guardDD); return result; }
/// <summary> /// /// </summary> /// <param name="processes"></param> /// <param name="model"></param> /// <param name="result"></param> private static void InterleaveEncodeChannel(List<AutomataBDD> processes, Model model, AutomataBDD result) { for (int i = 0; i < processes.Count; i++) { List<int> unchangedVariableIndex = new List<int>(result.variableIndex); foreach (int index in processes[i].variableIndex) { unchangedVariableIndex.Remove(index); } //Channel communication implicitly is not terminate transition CUDD.Ref(processes[i].channelInTransitionBDD); result.channelInTransitionBDD.AddRange(model.AddVarUnchangedConstraint(processes[i].channelInTransitionBDD, unchangedVariableIndex)); CUDD.Ref(processes[i].channelOutTransitionBDD); result.channelOutTransitionBDD.AddRange(model.AddVarUnchangedConstraint(processes[i].channelOutTransitionBDD, unchangedVariableIndex)); } InterleaveGetChannelTransition(processes, model, result); }
private static void WaitEncodeTransitionChannel(string state, int t, Model model, AutomataBDD result) { //1. state = t and event' = terminate and state' = t + 1 Expression guard; List<CUDDNode> guardDD; guard = Expression.AND(Expression.EQ(new Variable(state), new IntConstant(t)), Expression.AND(AutomataBDD.GetTerminateTransExpression(), new Assignment(state, new IntConstant(t + 1)))); guardDD = guard.TranslateBoolExpToBDD(model).GuardDDs; guardDD = model.AddVarUnchangedConstraint(guardDD, model.GlobalVarIndex); result.transitionBDD.AddRange(guardDD); }
/// <summary> /// (!temp ∧ event ' = terminate ∧ temp ') /// </summary> private static void SkipEncodeTransition(Model model, AutomataBDD result) { Expression guard = Expression.AND( Expression.AND( new PrimitiveApplication( PrimitiveApplication.EQUAL, new Variable(result.newLocalVarName), new IntConstant(0)), GetTerminateTransExpression()), new Assignment(result.newLocalVarName, new IntConstant(1))); result.transitionBDD.AddRange(model.AddVarUnchangedConstraint(guard.TranslateBoolExpToBDD(model).GuardDDs, model.GlobalVarIndex)); }
/// <summary> /// ∨ (Pi.transition ∧ unchanged.i) /// [ REFS: '', DEREFS: 'Pi.transitionBDD, priorityTransitionsBDD'] /// </summary> private static void InterleaveEncodeTransition(List<AutomataBDD> processes, Model model, AutomataBDD result) { foreach (var process in processes) { List<int> unchangedVariableIndex = new List<int>(result.variableIndex); foreach (int index in process.variableIndex) { unchangedVariableIndex.Remove(index); } process.transitionBDD = new List<CUDDNode>() {CUDD.Function.Or(process.transitionBDD)}; result.transitionBDD.AddRange(model.AddVarUnchangedConstraint(process.transitionBDD, unchangedVariableIndex)); } }
/// <summary> /// tau transition in process 2 does not resolve /// [ REFS: '', DEREFS: 'P1, P2'] /// </summary> /// <param name="P1"></param> /// <param name="P2"></param> /// <param name="model"></param> /// <param name="result"></param> private static void InterruptEncodeTransition(AutomataBDD P1, AutomataBDD P2, Model model, AutomataBDD result) { //1. (isInterrupted < 2 ∧ P1.Trans/In/Out ∧ [(event' = termination and isInterrupted' = 1) or (event' != termination and isInterrupted' = isInterrupted)] P2.var = P2.var') Expression guard = Expression.AND( Expression.LT(new Variable(result.newLocalVarName), new IntConstant(2)), Expression.OR( Expression.AND( GetTerminateTransExpression(), new Assignment(result.newLocalVarName, new IntConstant(1))), Expression.AND( GetNotTerminateTransExpression(), new Assignment(result.newLocalVarName, new Variable(result.newLocalVarName)))) ); List <CUDDNode> transition = guard.TranslateBoolExpToBDD(model).GuardDDs; transition = model.AddVarUnchangedConstraint(transition, P2.variableIndex); // CUDD.Ref(transition); result.transitionBDD.AddRange(CUDD.Function.And(transition, P1.transitionBDD)); CUDD.Ref(transition); result.channelInTransitionBDD.AddRange(CUDD.Function.And(transition, P1.channelInTransitionBDD)); result.channelOutTransitionBDD.AddRange(CUDD.Function.And(transition, P1.channelOutTransitionBDD)); //2. (isInterrupted != 1 ∧ P2.Trans/In/Out ∧ [(event' = tau and isInterrupted' = isInterrupted) or (event' != tau and isInterrupted' = 2)]) guard = Expression.AND( Expression.NE(new Variable(result.newLocalVarName), new IntConstant(1)), Expression.OR( Expression.AND( GetTauTransExpression(), new Assignment(result.newLocalVarName, new Variable(result.newLocalVarName))), Expression.AND( GetNotTauTransExpression(), new Assignment(result.newLocalVarName, new IntConstant(2)))) ); transition = guard.TranslateBoolExpToBDD(model).GuardDDs; // CUDD.Ref(transition); result.transitionBDD.AddRange(CUDD.Function.And(transition, P2.transitionBDD)); CUDD.Ref(transition); result.channelInTransitionBDD.AddRange(CUDD.Function.And(transition, P2.channelInTransitionBDD)); //CUDD.Ref(transition); result.channelOutTransitionBDD.AddRange(CUDD.Function.And(transition, P2.channelOutTransitionBDD)); }
/// <summary> /// tau transition in process 2 does not resolve /// [ REFS: '', DEREFS: 'P1, P2'] /// </summary> /// <param name="P1"></param> /// <param name="P2"></param> /// <param name="model"></param> /// <param name="result"></param> private static void InterruptEncodeTransition(AutomataBDD P1, AutomataBDD P2, Model model, AutomataBDD result) { //1. (isInterrupted < 2 ∧ P1.Trans/In/Out ∧ [(event' = termination and isInterrupted' = 1) or (event' != termination and isInterrupted' = isInterrupted)] P2.var = P2.var') Expression guard = Expression.AND( Expression.LT(new Variable(result.newLocalVarName), new IntConstant(2)), Expression.OR( Expression.AND( GetTerminateTransExpression(), new Assignment(result.newLocalVarName, new IntConstant(1))), Expression.AND( GetNotTerminateTransExpression(), new Assignment(result.newLocalVarName, new Variable(result.newLocalVarName)))) ); List<CUDDNode> transition = guard.TranslateBoolExpToBDD(model).GuardDDs; transition = model.AddVarUnchangedConstraint(transition, P2.variableIndex); // CUDD.Ref(transition); result.transitionBDD.AddRange(CUDD.Function.And(transition, P1.transitionBDD)); CUDD.Ref(transition); result.channelInTransitionBDD.AddRange(CUDD.Function.And(transition, P1.channelInTransitionBDD)); result.channelOutTransitionBDD.AddRange(CUDD.Function.And(transition, P1.channelOutTransitionBDD)); //2. (isInterrupted != 1 ∧ P2.Trans/In/Out ∧ [(event' = tau and isInterrupted' = isInterrupted) or (event' != tau and isInterrupted' = 2)]) guard = Expression.AND( Expression.NE(new Variable(result.newLocalVarName), new IntConstant(1)), Expression.OR( Expression.AND( GetTauTransExpression(), new Assignment(result.newLocalVarName, new Variable(result.newLocalVarName))), Expression.AND( GetNotTauTransExpression(), new Assignment(result.newLocalVarName, new IntConstant(2)))) ); transition = guard.TranslateBoolExpToBDD(model).GuardDDs; // CUDD.Ref(transition); result.transitionBDD.AddRange(CUDD.Function.And(transition, P2.transitionBDD)); CUDD.Ref(transition); result.channelInTransitionBDD.AddRange(CUDD.Function.And(transition, P2.channelInTransitionBDD)); //CUDD.Ref(transition); result.channelOutTransitionBDD.AddRange(CUDD.Function.And(transition, P2.channelOutTransitionBDD)); }
/// <summary> /// (!temp ∧ guard∧ ∧ update ∧ temp ' ∧ P1.init) /// </summary> private static void EventPrefixTransitition(Expression guardOfTrans, Expression updateOfTrans, AutomataBDD P1, Model model, AutomataBDD result) { Expression guard = new PrimitiveApplication(PrimitiveApplication.AND, new PrimitiveApplication(PrimitiveApplication.EQUAL, new Variable(result.newLocalVarName), new IntConstant(0)), guardOfTrans); Expression update = new Sequence(updateOfTrans, new Assignment(result.newLocalVarName, new IntConstant(1))); List <CUDDNode> transition = model.EncodeTransition(guard, update, new List <int>()); transition = CUDD.Function.And(transition, P1.GetInitInColumn(model)); transition = model.AddVarUnchangedConstraint(transition, model.GlobalVarIndex); result.transitionBDD.AddRange(transition); }
private static void WaitEncodeTick(string state, int t, Model model, AutomataBDD result) { //1. state < t and event' = tick and state' = state + 1 Expression guard; List<CUDDNode> guardDD; guard = Expression.AND(Expression.LT(new Variable(state), new IntConstant(t)), Expression.AND(GetTickTransExpression(), new Assignment(state, Expression.PLUS(new Variable(state), new IntConstant(1))))); guardDD = guard.TranslateBoolExpToBDD(model).GuardDDs; guardDD = model.AddVarUnchangedConstraint(guardDD, model.GlobalVarIndex); result.Ticks.AddRange(guardDD); //1. state = t and event' = tick and state' = t //1. state = t + 1 and event' = tick and state' = t + 1 guard = Expression.AND(Expression.OR( Expression.EQ(new Variable(state), new IntConstant(t)), Expression.EQ(new Variable(state), new IntConstant(t + 1))), Expression.AND(GetTickTransExpression(), new Assignment(state, new Variable(state)))); guardDD = guard.TranslateBoolExpToBDD(model).GuardDDs; guardDD = model.AddVarUnchangedConstraint(guardDD, model.GlobalVarIndex); result.Ticks.AddRange(guardDD); }
/// <summary> /// Return AutomataBDD of Interleave process /// </summary> /// <param name="processes">List of AutomataBDD of interleaving processes</param> /// <param name="model"></param> /// <returns></returns> public static AutomataBDD Interleave(List<AutomataBDD> processes, Model model) { AutomataBDD result = AutomataBDD.Interleave(processes, model); ParallelEncodeTick(processes, model, result); //Combine simulation relation result.SimulationRel = CUDD.Constant(1); foreach (var automataBdd in processes) { result.SimulationRel = CUDD.Function.And(result.SimulationRel, automataBdd.SimulationRel); } result.SimulationRel = model.AddVarUnchangedConstraint(result.SimulationRel, model.GlobalVarIndex); // return result; }
/// <summary> /// ∨ (Pi.transition ∧ unchanged.i) /// [ REFS: '', DEREFS: 'Pi.transitionBDD, priorityTransitionsBDD'] /// </summary> private static void InterleaveEncodeTransition(List <AutomataBDD> processes, Model model, AutomataBDD result) { foreach (var process in processes) { List <int> unchangedVariableIndex = new List <int>(result.variableIndex); foreach (int index in process.variableIndex) { unchangedVariableIndex.Remove(index); } process.transitionBDD = new List <CUDDNode>() { CUDD.Function.Or(process.transitionBDD) }; result.transitionBDD.AddRange(model.AddVarUnchangedConstraint(process.transitionBDD, unchangedVariableIndex)); } }
/// <summary> /// (temp = -1 and tau and temp' in [0, n-1]) /// (temp = i ∧ Pi.transition ∧ temp' = i) /// </summary> /// <param name="choices"></param> /// <param name="model"></param> /// <param name="result"></param> private static void InternalChoiceEncodeTransition(List <AutomataBDD> choices, Model model, AutomataBDD result) { //Tau transition resolves the choice Expression guard = Expression.AND( Expression.AND( new PrimitiveApplication( PrimitiveApplication.AND, new PrimitiveApplication( PrimitiveApplication.EQUAL, new Variable(result.newLocalVarName), new IntConstant(-1)), GetTauTransExpression()), new PrimitiveApplication( PrimitiveApplication.GREATER_EQUAL, new VariablePrime( result.newLocalVarName), new IntConstant(0))), Expression.LE( new VariablePrime(result.newLocalVarName), new IntConstant(choices.Count - 1))); List <CUDDNode> transition = guard.TranslateBoolExpToBDD(model).GuardDDs; model.AddVarUnchangedConstraint(transition, model.GlobalVarIndex); result.transitionBDD.AddRange(transition); //Copy transitions from other processes after the choice is resolved for (int i = 0; i < choices.Count; i++) { //(temp = i ∧ Pi.transition ∧ temp' = i) guard = Expression.AND(Expression.EQ(new Variable(result.newLocalVarName), new IntConstant(i)), new Assignment(result.newLocalVarName, new IntConstant(i))); transition = guard.TranslateBoolExpToBDD(model).GuardDDs; // CUDD.Ref(transition); result.transitionBDD.AddRange(CUDD.Function.And(transition, choices[i].transitionBDD)); CUDD.Ref(transition); result.channelInTransitionBDD.AddRange(CUDD.Function.And(transition, choices[i].channelInTransitionBDD)); result.channelOutTransitionBDD.AddRange(CUDD.Function.And(transition, choices[i].channelOutTransitionBDD)); } }
/// <summary> /// (temp = -1 and tau and temp' in [0, n-1]) /// (temp = i ∧ Pi.transition ∧ temp' = i) /// </summary> /// <param name="choices"></param> /// <param name="model"></param> /// <param name="result"></param> private static void InternalChoiceEncodeTransition(List<AutomataBDD> choices, Model model, AutomataBDD result) { //Tau transition resolves the choice Expression guard = Expression.AND( Expression.AND( new PrimitiveApplication( PrimitiveApplication.AND, new PrimitiveApplication( PrimitiveApplication.EQUAL, new Variable(result.newLocalVarName), new IntConstant(-1)), GetTauTransExpression()), new PrimitiveApplication( PrimitiveApplication.GREATER_EQUAL, new VariablePrime( result.newLocalVarName), new IntConstant(0))), Expression.LE( new VariablePrime(result.newLocalVarName), new IntConstant(choices.Count - 1))); List<CUDDNode> transition = guard.TranslateBoolExpToBDD(model).GuardDDs; model.AddVarUnchangedConstraint(transition, model.GlobalVarIndex); result.transitionBDD.AddRange(transition); //Copy transitions from other processes after the choice is resolved for (int i = 0; i < choices.Count; i++) { //(temp = i ∧ Pi.transition ∧ temp' = i) guard = Expression.AND(Expression.EQ(new Variable(result.newLocalVarName), new IntConstant(i)), new Assignment(result.newLocalVarName, new IntConstant(i))); transition = guard.TranslateBoolExpToBDD(model).GuardDDs; // CUDD.Ref(transition); result.transitionBDD.AddRange(CUDD.Function.And(transition, choices[i].transitionBDD)); CUDD.Ref(transition); result.channelInTransitionBDD.AddRange(CUDD.Function.And(transition, choices[i].channelInTransitionBDD)); result.channelOutTransitionBDD.AddRange(CUDD.Function.And(transition, choices[i].channelOutTransitionBDD)); } }
/// <summary> /// /// </summary> /// <param name="channelEventIndex"></param> /// <param name="exps">List of expressions of channel in</param> /// <param name="P1">Process after channel in</param> /// <param name="model">Process after channel in</param> /// <param name="result"></param> private static void SyncChannelOutputEncodeTransition(int channelEventIndex, List<Expression> exps, AutomataBDD P1, Model model, AutomataBDD result) { Expression guard = Expression.EQ(new Variable(result.newLocalVarName), new IntConstant(0)); Expression update = new Assignment(Model.EVENT_NAME, new IntConstant(channelEventIndex)); for (int i = 0; i < exps.Count; i++) { //Update eventParameterVariables[i] = exps[i] //Don't need to update exps because later after synchronization, not updated variable keeps the same value update = new Sequence(update, new Assignment(model.eventParameterVariables[i], exps[i])); } update = new Sequence(update, new Assignment(result.newLocalVarName, new IntConstant(1))); List<CUDDNode> transition = model.EncodeTransition(guard, update, new List<int>()); transition = CUDD.Function.And(transition, P1.GetInitInColumn(model)); transition = model.AddVarUnchangedConstraint(transition, model.GlobalVarIndex); result.channelOutTransitionBDD.AddRange(transition); // CopyTransitionAfterEventChannel(P1, model, result); }
/// <summary> /// /// </summary> /// <param name="channelEventIndex"></param> /// <param name="guard">If no guard, give BoolConstant(true)</param> /// <param name="exps">List of expressions of channel in</param> /// <param name="P1">Process after channel in</param> /// <param name="model"></param> /// <param name="result"></param> private static void SyncChannelInputEncodeTransition(int channelEventIndex, Expression guard, List<Expression> exps, AutomataBDD P1, Model model, AutomataBDD result) { //temp = result.processName //!temp and guard and event' = channelEventIndex and temp' and Update_Channel and P1.init' guard = Expression.AND(guard, Expression.EQ(new Variable(result.newLocalVarName), new IntConstant(0))); guard = Expression.AND(guard, new Assignment(Model.EVENT_NAME, new IntConstant(channelEventIndex))); guard = Expression.AND(guard, new Assignment(result.newLocalVarName, new IntConstant(1))); for (int i = 0; i < exps.Count; i++) { if (exps[i] is IntConstant) { //eventParameterVariables[i]' = exps[i] guard = Expression.AND(guard, new Assignment(model.eventParameterVariables[i], exps[i])); } else { //eventParameterVariables[i]' = exps[i]' guard = Expression.AND(guard, Expression.EQ(new VariablePrime(model.eventParameterVariables[i]), new VariablePrime(exps[i].expressionID))); } } // List<CUDDNode> transition = guard.TranslateBoolExpToBDD(model).GuardDDs; transition = CUDD.Function.And(transition, P1.GetInitInColumn(model)); transition = model.AddVarUnchangedConstraint(transition, model.GlobalVarIndex); result.channelInTransitionBDD.AddRange(transition); // CopyTransitionAfterEventChannel(P1, model, result); }
/// <summary> /// /// </summary> /// <param name="channelEventIndex"></param> /// <param name="exps">List of expressions of channel in</param> /// <param name="P1">Process after channel in</param> /// <param name="model">Process after channel in</param> /// <param name="result"></param> private static void SyncChannelOutputEncodeTransition(int channelEventIndex, List <Expression> exps, AutomataBDD P1, Model model, AutomataBDD result) { Expression guard = Expression.EQ(new Variable(result.newLocalVarName), new IntConstant(0)); Expression update = new Assignment(Model.EVENT_NAME, new IntConstant(channelEventIndex)); for (int i = 0; i < exps.Count; i++) { //Update eventParameterVariables[i] = exps[i] //Don't need to update exps because later after synchronization, not updated variable keeps the same value update = new Sequence(update, new Assignment(model.eventParameterVariables[i], exps[i])); } update = new Sequence(update, new Assignment(result.newLocalVarName, new IntConstant(1))); List <CUDDNode> transition = model.EncodeTransition(guard, update, new List <int>()); transition = CUDD.Function.And(transition, P1.GetInitInColumn(model)); transition = model.AddVarUnchangedConstraint(transition, model.GlobalVarIndex); result.channelOutTransitionBDD.AddRange(transition); // CopyTransitionAfterEventChannel(P1, model, result); }
/// <summary> /// /// </summary> /// <param name="channelEventIndex"></param> /// <param name="guard">If no guard, give BoolConstant(true)</param> /// <param name="exps">List of expressions of channel in</param> /// <param name="P1">Process after channel in</param> /// <param name="model"></param> /// <param name="result"></param> private static void SyncChannelInputEncodeTransition(int channelEventIndex, Expression guard, List <Expression> exps, AutomataBDD P1, Model model, AutomataBDD result) { //temp = result.processName //!temp and guard and event' = channelEventIndex and temp' and Update_Channel and P1.init' guard = new PrimitiveApplication(PrimitiveApplication.AND, guard, new PrimitiveApplication(PrimitiveApplication.EQUAL, new Variable(result.newLocalVarName), new IntConstant(0))); guard = new PrimitiveApplication(PrimitiveApplication.AND, guard, new Assignment(Model.EVENT_NAME, new IntConstant(channelEventIndex))); guard = new PrimitiveApplication(PrimitiveApplication.AND, guard, new Assignment(result.newLocalVarName, new IntConstant(1))); for (int i = 0; i < exps.Count; i++) { if (exps[i] is IntConstant) { //eventParameterVariables[i]' = exps[i] guard = new PrimitiveApplication(PrimitiveApplication.AND, guard, new Assignment(model.eventParameterVariables[i], exps[i])); } else { //eventParameterVariables[i]' = exps[i]' guard = new PrimitiveApplication(PrimitiveApplication.AND, guard, new PrimitiveApplication(PrimitiveApplication.EQUAL, new VariablePrime(model.eventParameterVariables[i]), new VariablePrime(exps[i].expressionID))); } } // List <CUDDNode> transition = guard.TranslateBoolExpToBDD(model).GuardDDs; transition = CUDD.Function.And(transition, P1.GetInitInColumn(model)); transition = model.AddVarUnchangedConstraint(transition, model.GlobalVarIndex); result.channelInTransitionBDD.AddRange(transition); // CopyTransitionAfterEventChannel(P1, model, result); }
/// <summary> /// Tau transition ∧ ((temp = -1 and temp' = -1 and other unchanged) or (temp = i and temp' = i) /// (temp = i or temp = -1) and Not Tau Transition ∧ temp' = i; /// If Tau transitions happens first then temp still not initialized. /// After Not Tau Transition happen, then temp is initialize. Later although Tau transition can happen, this selection is not changed. /// [ REFS: 'none', DEREFS: 'choices, tauEvent' ] /// </summary> /// <param name="choices"></param> /// <param name="model"></param> /// <param name="result"></param> private static void ExternalChoiceEncodeTransition(List<AutomataBDD> choices, Model model, AutomataBDD result) { for (int i = 0; i < choices.Count; i++) { //2. (temp = i or temp = -1) and Not Tau Transition ∧ temp' = i Expression guard = Expression.OR( Expression.EQ( new Variable(result.newLocalVarName), new IntConstant(-1)), Expression.EQ( new Variable(result.newLocalVarName), new IntConstant(i))); guard = Expression.AND(guard, new Assignment(result.newLocalVarName, new IntConstant(i))); List<CUDDNode> transition = guard.TranslateBoolExpToBDD(model).GuardDDs; CUDD.Ref(transition); List<CUDDNode> notTauTransition = CUDD.Function.And(transition, CUDD.Function.Not(GetTauTransEncoding(model))); // CUDD.Ref(choices[i].transitionBDD); result.transitionBDD.AddRange(CUDD.Function.And(choices[i].transitionBDD, notTauTransition)); //Channel communication vacuously is not tau transition CUDD.Ref(transition); result.channelInTransitionBDD.AddRange(CUDD.Function.And(choices[i].channelInTransitionBDD, transition)); result.channelOutTransitionBDD.AddRange(CUDD.Function.And(choices[i].channelOutTransitionBDD, transition)); //1. Tau transition ∧ ((temp = -1 and temp' = -1 and other unchanged) or (temp = i and temp' = i) guard = Expression.OR( Expression.AND( new PrimitiveApplication( PrimitiveApplication.EQUAL, new Variable(result.newLocalVarName), new IntConstant(-1)), new Assignment(result.newLocalVarName, new IntConstant(-1))), Expression.AND( new PrimitiveApplication( PrimitiveApplication.EQUAL, new Variable(result.newLocalVarName), new IntConstant(i)), new Assignment(result.newLocalVarName, new IntConstant(-1)))); transition = guard.TranslateBoolExpToBDD(model).GuardDDs; List<CUDDNode> tauTransition = CUDD.Function.And(choices[i].transitionBDD, GetTauTransEncoding(model)); transition = CUDD.Function.And(transition, tauTransition); //already includes temp List<int> unchangedVariableIndex = new List<int>(result.variableIndex); foreach (int index in choices[i].variableIndex) { unchangedVariableIndex.Remove(index); } model.AddVarUnchangedConstraint(transition, unchangedVariableIndex); result.transitionBDD.AddRange(transition); } }
/// <summary> /// Get new Transition from Channel input, channel ouput of sub processes /// [ REFS: '', DEREFS: 'processes.channelInTransitionBDD, channelOutTransitionBDD'] /// </summary> /// <param name="processes"></param> /// <param name="model"></param> /// <param name="result"></param> private static void InterleaveGetChannelTransition(List<AutomataBDD> processes, Model model, AutomataBDD result) { List<CUDDNode> syncedChannelTransition = new List<CUDDNode>(); //Make sure only 2 different processes can join the synchronized channel event for (int i = 0; i < processes.Count; i++) { for (int j = i + 1; j < processes.Count; j++) { if (processes[i].channelInTransitionBDD.Count > 0 && processes[j].channelOutTransitionBDD.Count > 0) { //process i Channel Input, process j Channel Output CUDD.Ref(processes[i].channelInTransitionBDD); CUDD.Ref(processes[j].channelOutTransitionBDD); syncedChannelTransition.AddRange(CUDD.Function.And(processes[i].channelInTransitionBDD, processes[j].channelOutTransitionBDD)); } if (processes[i].channelOutTransitionBDD.Count > 0 && processes[j].channelInTransitionBDD.Count > 0) { //Process i Channel Output, Process j Channel Input CUDD.Ref(processes[i].channelOutTransitionBDD); CUDD.Ref(processes[j].channelInTransitionBDD); syncedChannelTransition.AddRange(CUDD.Function.And(processes[i].channelOutTransitionBDD, processes[j].channelInTransitionBDD)); } } } //Dereference the Channel input, channel output of all sub processes foreach (AutomataBDD process in processes) { CUDD.Deref(process.channelInTransitionBDD, process.channelOutTransitionBDD); } //2 processes join in the channel sycchronized event, other must be unchanged syncedChannelTransition = model.AddVarUnchangedConstraint(syncedChannelTransition, result.variableIndex); syncedChannelTransition = model.AddVarUnchangedConstraint(syncedChannelTransition, model.GlobalVarIndex); // if (syncedChannelTransition.Count > 0) { result.transitionBDD.Add(CUDD.Function.Or(syncedChannelTransition)); } }
/// <summary> /// syncTransition = P1.transition ∧ P2.transition /// syncEvent: formula of synchronized events /// P.transition = syncTransition ∨ (Pi.transition ∧ !syncEvent ∧ unchanged.i) /// Applied this formula for each pair of process: P1 || P2 || P3 = (P1 || P2) || P3 /// [ REFS: '', DEREFS: 'processes[i].transitionBDD, alphabet'] /// </summary> /// <param name="processes"></param> /// <param name="alphabets">alphabet of each process if provided. Give True if not provided</param> /// <param name="model"></param> /// <param name="result"></param> private static void ParallelEncodeTransition(List<AutomataBDD> processes, List<CUDDNode> alphabets, Model model, AutomataBDD result) { List<CUDDNode> transition = processes[0].transitionBDD; CUDDNode lastAlphabet = alphabets[0]; //Do encoding at each step, 2 processes once for (int i = 1; i < processes.Count; i++) { //find sync transitions CUDD.Ref(transition); CUDD.Ref(processes[i].transitionBDD); List<CUDDNode> syncTransition = CUDD.Function.And(transition, processes[i].transitionBDD); //sync alphabet = (P0.alphabet and P1.alphabet) or termination event //We rename the event with assignment whose name may be also in the alphabet //After the rename, they do not belong to the alphabet CUDD.Ref(lastAlphabet, alphabets[i]); CUDDNode syncEvent = CUDD.Function.Or(CUDD.Function.And(lastAlphabet, alphabets[i]), GetTerminationTransEncoding(model)); //sync transition must have no program block which mean no global variable updated foreach (var globalVarIndex in model.GlobalVarIndex) { CUDD.Ref(model.varIdentities[globalVarIndex]); syncEvent = CUDD.Function.And(syncEvent, model.varIdentities[globalVarIndex]); } CUDD.Ref(syncEvent); syncTransition = CUDD.Function.And(syncTransition, syncEvent); //update current alphabet lastAlphabet = CUDD.Function.Or(lastAlphabet, alphabets[i]); CUDD.Ref(syncTransition); List<CUDDNode> tempTransition = new List<CUDDNode>(syncTransition); //find not sync event, we need to add global variable unchanged to syncEvent because for example process a -> a {x = 1} -> P; //a may be in the alphabet, and the first a can be synced, but the secondtion is not CUDDNode notSyncEvents = CUDD.Function.Not(syncEvent); CUDD.Ref(notSyncEvents); tempTransition.AddRange(CUDD.Function.And(transition, notSyncEvents)); tempTransition.AddRange(CUDD.Function.And(processes[i].transitionBDD, notSyncEvents)); transition = tempTransition; } // CUDD.Deref(lastAlphabet); transition = model.AddVarUnchangedConstraint(transition, result.variableIndex); // result.transitionBDD = transition; }
/// <summary> /// (!temp ∧ guard∧ ∧ update ∧ temp ' ∧ P1.init) /// </summary> private static void EventPrefixTransitition(Expression guardOfTrans, Expression updateOfTrans, AutomataBDD P1, Model model, AutomataBDD result) { Expression guard = Expression.AND(Expression.EQ(new Variable(result.newLocalVarName), new IntConstant(0)), guardOfTrans); Expression update = new Sequence(updateOfTrans, new Assignment(result.newLocalVarName, new IntConstant(1))); List<CUDDNode> transition = model.EncodeTransition(guard, update, new List<int>()); transition = CUDD.Function.And(transition, P1.GetInitInColumn(model)); transition = model.AddVarUnchangedConstraint(transition, model.GlobalVarIndex); result.transitionBDD.AddRange(transition); }
/// <summary> /// Tau transition ∧ ((temp = -1 and temp' = -1 and other unchanged) or (temp = i and temp' = i) /// (temp = i or temp = -1) and Not Tau Transition ∧ temp' = i; /// If Tau transitions happens first then temp still not initialized. /// After Not Tau Transition happen, then temp is initialize. Later although Tau transition can happen, this selection is not changed. /// [ REFS: 'none', DEREFS: 'choices, tauEvent' ] /// </summary> /// <param name="choices"></param> /// <param name="model"></param> /// <param name="result"></param> private static void ExternalChoiceEncodeTransition(List <AutomataBDD> choices, Model model, AutomataBDD result) { for (int i = 0; i < choices.Count; i++) { //2. (temp = i or temp = -1) and Not Tau Transition ∧ temp' = i Expression guard = Expression.OR( Expression.EQ( new Variable(result.newLocalVarName), new IntConstant(-1)), Expression.EQ( new Variable(result.newLocalVarName), new IntConstant(i))); guard = Expression.AND(guard, new Assignment(result.newLocalVarName, new IntConstant(i))); List <CUDDNode> transition = guard.TranslateBoolExpToBDD(model).GuardDDs; CUDD.Ref(transition); List <CUDDNode> notTauTransition = CUDD.Function.And(transition, CUDD.Function.Not(GetTauTransEncoding(model))); // CUDD.Ref(choices[i].transitionBDD); result.transitionBDD.AddRange(CUDD.Function.And(choices[i].transitionBDD, notTauTransition)); //Channel communication vacuously is not tau transition CUDD.Ref(transition); result.channelInTransitionBDD.AddRange(CUDD.Function.And(choices[i].channelInTransitionBDD, transition)); result.channelOutTransitionBDD.AddRange(CUDD.Function.And(choices[i].channelOutTransitionBDD, transition)); //1. Tau transition ∧ ((temp = -1 and temp' = -1 and other unchanged) or (temp = i and temp' = i) guard = Expression.OR( Expression.AND( new PrimitiveApplication( PrimitiveApplication.EQUAL, new Variable(result.newLocalVarName), new IntConstant(-1)), new Assignment(result.newLocalVarName, new IntConstant(-1))), Expression.AND( new PrimitiveApplication( PrimitiveApplication.EQUAL, new Variable(result.newLocalVarName), new IntConstant(i)), new Assignment(result.newLocalVarName, new IntConstant(-1)))); transition = guard.TranslateBoolExpToBDD(model).GuardDDs; List <CUDDNode> tauTransition = CUDD.Function.And(choices[i].transitionBDD, GetTauTransEncoding(model)); transition = CUDD.Function.And(transition, tauTransition); //already includes temp List <int> unchangedVariableIndex = new List <int>(result.variableIndex); foreach (int index in choices[i].variableIndex) { unchangedVariableIndex.Remove(index); } model.AddVarUnchangedConstraint(transition, unchangedVariableIndex); result.transitionBDD.AddRange(transition); } }