/// <summary> /// 1. Interrupt is not resolved, time evolution is synchronized /// 2. P1 terminate, or P2 interrupt, not need synchronization /// </summary> /// <param name="P1"></param> /// <param name="P2"></param> /// <param name="model"></param> /// <param name="result"></param> private static void InterruptEncodeTick(AutomataBDD P1, AutomataBDD P2, Model model, AutomataBDD result) { //1. (isInterrupted = 0 ∧ P1.Tick ∧ P2.Tick ∧ isInterrupted' = 0) Expression guard = Expression.EQ(new Variable(result.newLocalVarName), new IntConstant(0)); Expression update = new Assignment(result.newLocalVarName, new IntConstant(0)); List<CUDDNode> transition = model.EncodeTransition(guard, update, new List<int>()); CUDD.Ref(P2.Ticks); transition = CUDD.Function.And(CUDD.Function.And(transition, P1.Ticks), P2.Ticks); result.Ticks.AddRange(CUDD.Function.And(transition, P1.Ticks)); //2. (isInterrupted = 1 and P1.tick ∧ isInterrupted' = 1) guard = Expression.EQ(new Variable(result.newLocalVarName), new IntConstant(1)); update = new Assignment(result.newLocalVarName, new IntConstant(1)); transition = model.EncodeTransition(guard, update, new List<int>()); result.Ticks.AddRange(CUDD.Function.And(transition, P1.Ticks)); //3. (isInterrupted = 2 and P2.tick ∧ isInterrupted' = 2) guard = Expression.EQ(new Variable(result.newLocalVarName), new IntConstant(2)); update = new Assignment(result.newLocalVarName, new IntConstant(2)); transition = model.EncodeTransition(guard, update, new List<int>()); result.Ticks.AddRange(CUDD.Function.And(transition, P2.Ticks)); }
/// <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> /// Encode this assignment in a sequence of statements. Return variable values after this assignment based on the current value in resultBefore /// [ REFS: 'result', DEREFS: 'resultBefore' ] /// </summary> public override ExpressionBDDEncoding TranslateStatementToBDD(ExpressionBDDEncoding resultBefore, Model model) { ExpressionBDDEncoding newUpdate = this.TranslateBoolExpToBDD(model); ExpressionBDDEncoding tempResult = new ExpressionBDDEncoding(); List<List<int>> updatedVariablesInNewUpdate = new List<List<int>>(); for (int index = 0; index < newUpdate.Count(); index++) { updatedVariablesInNewUpdate.Add(model.GetColSupportedVars(newUpdate.GuardDDs[index])); } List<List<int>> usedVariableInNewUpdate = new List<List<int>>(); for (int index = 0; index < newUpdate.Count(); index++) { usedVariableInNewUpdate.Add(model.GetRowSupportedVars(newUpdate.GuardDDs[index])); } List<List<int>> updatedVariablesBefore = new List<List<int>>(); for (int index = 0; index < resultBefore.Count(); index++) { updatedVariablesBefore.Add(model.GetColSupportedVars(resultBefore.GuardDDs[index])); } for (int j1 = 0; j1 < resultBefore.Count(); j1++) { for (int j2 = 0; j2 < newUpdate.Count(); j2++) { //a variable is already updated, now is updated again and it also apprears in the value expression if (Assignment.IsComplexUpdate(updatedVariablesBefore[j1], updatedVariablesInNewUpdate[j2], usedVariableInNewUpdate[j2])) { model.CreateTemporaryVar(); Expression newUpdate1; Expression newUpdate2; PropertyAssignment assignment = this as PropertyAssignment; newUpdate1 = new Assignment(Model.TEMPORARY_VARIABLE, this.RightHandExpression); newUpdate2 = new PropertyAssignment(this.RecordExpression, this.PropertyExpression, new Variable(Model.TEMPORARY_VARIABLE)); resultBefore.Ref(); ExpressionBDDEncoding tempResult1 = newUpdate1.TranslateStatementToBDD(resultBefore, model); ExpressionBDDEncoding tempResult2 = newUpdate2.TranslateStatementToBDD(tempResult1, model); //Remove the temporary variable from transition for (int i = 0; i < tempResult2.Count(); i++) { tempResult2.GuardDDs[i] = CUDD.Abstract.ThereExists(tempResult2.GuardDDs[i], model.GetRowVars(Model.TEMPORARY_VARIABLE)); tempResult2.GuardDDs[i] = CUDD.Abstract.ThereExists(tempResult2.GuardDDs[i], model.GetColVars(Model.TEMPORARY_VARIABLE)); tempResult.AddNodeToGuard(tempResult2.GuardDDs[i]); } } else { //swap row, col updated variable in result in the new update command expression CUDDNode update2 = newUpdate.GuardDDs[j2]; CUDD.Ref(update2); foreach (int index in updatedVariablesBefore[j1]) { if (usedVariableInNewUpdate[j2].Contains(index)) { update2 = CUDD.Variable.SwapVariables(update2, model.GetColVars(index), model.GetRowVars(index)); } } //Restrict updated variable in new update of the old update CUDDNode update1 = resultBefore.GuardDDs[j1]; CUDD.Ref(update1); foreach (int index in updatedVariablesInNewUpdate[j2]) { if (updatedVariablesBefore[j1].Contains(index)) { update1 = CUDD.Abstract.ThereExists(update1, model.GetColVars(index)); } } CUDDNode transition = CUDD.Function.And(update1, update2); tempResult.AddNodeToGuard(transition); } } } resultBefore.DeRef(); newUpdate.DeRef(); return tempResult; }
/// <summary> /// Encode transition, if it is synchronized, then we don't add constraint of unchanged global variables /// Parallel process only synchorinize event which does not change global variable or each transition changes same to global variables /// 3 kinds of transition: normal event, async channel input and async channel output /// </summary> /// <param name="encoder"></param> /// <param name="processVariableName"></param> /// <param name="localVars">Local of the current SymbolicLTS is unchanged</param> /// <param name="isSynchronized"></param> /// <returns></returns> public List<CUDDNode> Encode(BDDEncoder encoder, string processVariableName, List<int> localVars, bool isSynchronized) { Expression guardExpressions = Expression.EQ( new Variable(processVariableName), new IntConstant(encoder.stateIndexOfCurrentProcess[this.FromState.ID])); guardExpressions = Expression.CombineGuard(guardExpressions, GuardCondition); Expression eventUpdateExpression; if (this.Event is BDDEncoder.EventChannelInfo) { int channelIndex = encoder.GetChannelIndex(this.Event.BaseName, (this.Event as BDDEncoder.EventChannelInfo).type); eventUpdateExpression = new Assignment(Model.EVENT_NAME, new IntConstant(channelIndex)); } else { eventUpdateExpression = encoder.GetEventExpression(this.Event); } Assignment stateUpdateExpression = new Assignment(processVariableName, new IntConstant(encoder.stateIndexOfCurrentProcess[this.ToState.ID])); Sequence updateExpressions = new Sequence(eventUpdateExpression, stateUpdateExpression); if (this.ProgramBlock != null) { updateExpressions = new Sequence(updateExpressions, this.ProgramBlock); } List<int> unchangedVars = new List<int>(localVars); if (!isSynchronized) { unchangedVars.AddRange(encoder.model.GlobalVarIndex); } return encoder.model.EncodeTransition(guardExpressions, updateExpressions, unchangedVars); }
/// <summary> /// Return the event update expression when the event is a string like "event.0" /// </summary> /// <param name="eventName"></param> /// <returns></returns> private Expression GetEventExpression(string eventName) { string[] eventsTemp = eventName.Split('.', '[', ']'); List<string> events = new List<string>(); for (int i = 0; i < eventsTemp.Length; i++) { if (!string.IsNullOrEmpty(eventsTemp[i])) { events.Add(eventsTemp[i]); } } Expression eventExpression = new Assignment(Model.EVENT_NAME, new IntConstant(this.GetEventIndex(events[0], events.Count - 1))); for (int i = 1; i < events.Count; i++) { eventExpression = new Sequence(eventExpression, new Assignment(this.model.eventParameterVariables[i - 1], new IntConstant(int.Parse(events[i])))); } return eventExpression; }
/// <summary> /// Return the update event expression when the Event is an Event object /// </summary> /// <param name="Event"></param> /// <returns></returns> public Expression GetEventExpression(Event Event) { List<Expression> parameters = this.GetParaExpInEvent(Event); int eventIndex = this.GetEventIndex(Event.BaseName, parameters.Count); Expression eventUpdateExpression = new Assignment(Model.EVENT_NAME, new IntConstant(eventIndex)); if (parameters.Count > 0) { for (int i = 0; i < parameters.Count; i++) { eventUpdateExpression = new Sequence(eventUpdateExpression, new Assignment(this.model.eventParameterVariables[i], parameters[i])); } } return eventUpdateExpression; }
/// <summary> /// Encode this assignment in a sequence of statements. Return variable values after this assignment based on the current value in resultBefore /// [ REFS: 'result', DEREFS: 'resultBefore' ] /// </summary> public override ExpressionBDDEncoding TranslateStatementToBDD(ExpressionBDDEncoding resultBefore, Model model) { ExpressionBDDEncoding newUpdate = this.TranslateBoolExpToBDD(model); ExpressionBDDEncoding tempResult = new ExpressionBDDEncoding(); List <List <int> > updatedVariablesInNewUpdate = new List <List <int> >(); for (int index = 0; index < newUpdate.Count(); index++) { updatedVariablesInNewUpdate.Add(model.GetColSupportedVars(newUpdate.GuardDDs[index])); } List <List <int> > usedVariableInNewUpdate = new List <List <int> >(); for (int index = 0; index < newUpdate.Count(); index++) { usedVariableInNewUpdate.Add(model.GetRowSupportedVars(newUpdate.GuardDDs[index])); } List <List <int> > updatedVariablesBefore = new List <List <int> >(); for (int index = 0; index < resultBefore.Count(); index++) { updatedVariablesBefore.Add(model.GetColSupportedVars(resultBefore.GuardDDs[index])); } for (int j1 = 0; j1 < resultBefore.Count(); j1++) { for (int j2 = 0; j2 < newUpdate.Count(); j2++) { //a variable is already updated, now is updated again and it also apprears in the value expression if (Assignment.IsComplexUpdate(updatedVariablesBefore[j1], updatedVariablesInNewUpdate[j2], usedVariableInNewUpdate[j2])) { model.CreateTemporaryVar(); Expression newUpdate1; Expression newUpdate2; PropertyAssignment assignment = this as PropertyAssignment; newUpdate1 = new Assignment(Model.TEMPORARY_VARIABLE, this.RightHandExpression); newUpdate2 = new PropertyAssignment(this.RecordExpression, this.PropertyExpression, new Variable(Model.TEMPORARY_VARIABLE)); resultBefore.Ref(); ExpressionBDDEncoding tempResult1 = newUpdate1.TranslateStatementToBDD(resultBefore, model); ExpressionBDDEncoding tempResult2 = newUpdate2.TranslateStatementToBDD(tempResult1, model); //Remove the temporary variable from transition for (int i = 0; i < tempResult2.Count(); i++) { tempResult2.GuardDDs[i] = CUDD.Abstract.ThereExists(tempResult2.GuardDDs[i], model.GetRowVars(model.GetVarIndex(Model.TEMPORARY_VARIABLE))); tempResult2.GuardDDs[i] = CUDD.Abstract.ThereExists(tempResult2.GuardDDs[i], model.GetColVars(model.GetVarIndex(Model.TEMPORARY_VARIABLE))); tempResult.AddNodeToGuard(tempResult2.GuardDDs[i]); } } else { //swap row, col updated variable in result in the new update command expression CUDDNode update2 = newUpdate.GuardDDs[j2]; CUDD.Ref(update2); foreach (int index in updatedVariablesBefore[j1]) { if (usedVariableInNewUpdate[j2].Contains(index)) { update2 = CUDD.Variable.SwapVariables(update2, model.GetColVars(index), model.GetRowVars(index)); } } //Restrict updated variable in new update of the old update CUDDNode update1 = resultBefore.GuardDDs[j1]; CUDD.Ref(update1); foreach (int index in updatedVariablesInNewUpdate[j2]) { if (updatedVariablesBefore[j1].Contains(index)) { update1 = CUDD.Abstract.ThereExists(update1, model.GetColVars(index)); } } CUDDNode transition = CUDD.Function.And(update1, update2); tempResult.AddNodeToGuard(transition); } } } resultBefore.DeRef(); newUpdate.DeRef(); return(tempResult); }