private SystemDDs EncodeSingleModule(SingleModuleSystem system, List <int> currentAvailStartBits) { int moduleIndex = modules.GetModuleIndex(system.moduleName); Module module = modules.GetModule(moduleIndex); SystemDDs result = new SystemDDs(); //encode not sync command result.ind = EncodeModule(moduleIndex, module, string.Empty, 0); // build mtbdd for each synchronising action for (int i = 0; i < synchs.Count; i++) { result.synchs.Add(EncodeModule(moduleIndex, module, synchs.ElementAt(i), currentAvailStartBits[i])); } // store identity matrix CUDD.Ref(moduleIdentities[moduleIndex]); result.id = moduleIdentities[moduleIndex]; // store synchs used result.allSynchs.UnionWith(module.GetAllSynchs()); return(result); }
private SystemDDs EncodeFullParallelSystem(FullParallelSystem sys, List <int> currentAvailStartBits) { SystemDDs sysDDs1, sysDDs2, sysDDs; List <int> newCurrentAvailStartBits = new List <int>(); int i, j; // construct mtbdds for first operand sysDDs = EncodeSystemDefRec(sys.GetSystem(0), currentAvailStartBits); // loop through all other operands in the parallel operator for (i = 1; i < sys.NumberSystem; i++) { // change min to max for potentially synchronising actions // store this in new array - old one may still be used elsewhere for (j = 0; j < synchs.Count; j++) { int newValue = (sysDDs.allSynchs.Contains(synchs[j])) ? sysDDs.synchs[j].max : currentAvailStartBits[j]; newCurrentAvailStartBits.Add(newValue); } // construct mtbdds for next operand sysDDs2 = EncodeSystemDefRec(sys.GetSystem(i), newCurrentAvailStartBits); // move sysDDs (operands composed so far) into sysDDs1 sysDDs1 = sysDDs; // we are going to combine sysDDs1 and sysDDs2 and put the result into sysDDs sysDDs = new SystemDDs(); // combine mtbdds for independent bit sysDDs.ind = CombineNonSynchronising(sysDDs1.ind, sysDDs2.ind, sysDDs1.id, sysDDs2.id); // combine mtbdds for each synchronising action for (j = 0; j < synchs.Count; j++) { // do asynchronous parallel composition if ((sysDDs1.allSynchs.Contains(synchs.ElementAt(j)) ? 1 : 0) + (sysDDs2.allSynchs.Contains(synchs.ElementAt(j)) ? 1 : 0) == 1) { sysDDs.synchs.Add(CombineNonSynchronising(sysDDs1.synchs[j], sysDDs2.synchs[j], sysDDs1.id, sysDDs2.id)); } else { sysDDs.synchs.Add(CombineSynchronising(sysDDs1.synchs[j], sysDDs2.synchs[j])); } } // compute identity sysDDs.id = CUDD.Function.Times(sysDDs1.id, sysDDs2.id); // combine lists of synchs sysDDs.allSynchs.UnionWith(sysDDs1.allSynchs); sysDDs.allSynchs.UnionWith(sysDDs2.allSynchs); } return(sysDDs); }
private SystemDDs EncodeParallel(ParallelSystem sys, List <int> currentAvailStartBits) { SystemDDs sysDDs1, sysDDs2, sysDDs; List <bool> synchBool = new List <bool>(); for (int i = 0; i < synchs.Count; i++) { synchBool[i] = sys.ContainsAction(synchs[i]); } // construct mtbdds for first operand sysDDs1 = EncodeSystemDefRec(sys.system1, currentAvailStartBits); List <int> newCurrentAvailStartBits = new List <int>(); for (int i = 0; i < synchs.Count; i++) { newCurrentAvailStartBits[i] = synchBool[i] ? sysDDs1.synchs[i].max : currentAvailStartBits[i]; } // construct mtbdds for second operand sysDDs2 = EncodeSystemDefRec(sys.system2, newCurrentAvailStartBits); // create object to store mtbdds sysDDs = new SystemDDs(); // combine mtbdds for independent bit sysDDs.ind = CombineNonSynchronising(sysDDs1.ind, sysDDs2.ind, sysDDs1.id, sysDDs2.id); // combine mtbdds for each synchronising action for (int i = 0; i < synchs.Count; i++) { if (synchBool[i]) { sysDDs.synchs.Add(CombineSynchronising(sysDDs1.synchs[i], sysDDs2.synchs[i])); } else { sysDDs.synchs.Add(CombineNonSynchronising(sysDDs1.synchs[i], sysDDs2.synchs[i], sysDDs1.id, sysDDs2.id)); } } // combine mtbdds for identity matrices sysDDs.id = CUDD.Function.Times(sysDDs1.id, sysDDs2.id); // combine lists of synchs sysDDs.allSynchs.UnionWith(sysDDs1.allSynchs); sysDDs.allSynchs.UnionWith(sysDDs2.allSynchs); return(sysDDs); }
private SystemDDs EncodeInterelave(InterleaveSystem system, List <int> currentAvailStartBits) { SystemDDs sysDDs1, sysDDs2, sysDDs; int i, j; // construct mtbdds for first operand sysDDs = EncodeSystemDefRec(system.GetSystem(0), currentAvailStartBits); // loop through all other operands in the parallel operator for (i = 1; i < system.NumberSystem; i++) { // construct mtbdds for next operand sysDDs2 = EncodeSystemDefRec(system.GetSystem(i), currentAvailStartBits); // move sysDDs (operands composed so far) into sysDDs1 sysDDs1 = sysDDs; // we are going to combine sysDDs1 and sysDDs2 and put the result into sysDDs sysDDs = new SystemDDs(); // combine mtbdds for independent bit sysDDs.ind = CombineNonSynchronising(sysDDs1.ind, sysDDs2.ind, sysDDs1.id, sysDDs2.id); // combine mtbdds for each synchronising action for (j = 0; j < synchs.Count; j++) { sysDDs.synchs.Add(CombineNonSynchronising(sysDDs1.synchs[j], sysDDs2.synchs[j], sysDDs1.id, sysDDs2.id)); } // compute identity sysDDs.id = CUDD.Function.Times(sysDDs1.id, sysDDs2.id); // combine lists of synchs sysDDs.allSynchs.UnionWith(sysDDs1.allSynchs); sysDDs.allSynchs.UnionWith(sysDDs2.allSynchs); } return(sysDDs); }
private void EncodeSystemDef(SystemDef system) { List <int> currentAvailStartBits = new List <int>(); for (int i = 0; i < synchs.Count; i++) { currentAvailStartBits.Add(0); } SystemDDs sysDDs = EncodeSystemDefRec(system, currentAvailStartBits); // for the nondeterministic case, add extra mtbdd variables to encode nondeterminism if (modules.modelType == ModelType.MDP) { int max = sysDDs.ind.max; for (int i = 0; i < synchs.Count; i++) { if (sysDDs.synchs[i].max > max) { max = sysDDs.synchs[i].max; } } //update max sysDDs.ind.max = max; for (int i = 0; i < synchs.Count; i++) { sysDDs.synchs[i].max = max; } //TODO Different from Prism // now add in new mtbdd variables to distinguish between actions //index 0 for empty label CUDDNode tmp = CUDD.Matrix.SetVectorElement(CUDD.Constant(0), allSynchVars, 0, 1); sysDDs.ind.trans = CUDD.Function.Times(tmp, sysDDs.ind.trans); // synchronous bits //1... for other labels for (int i = 0; i < synchs.Count; i++) { tmp = CUDD.Matrix.SetVectorElement(CUDD.Constant(0), allSynchVars, i + 1, 1); sysDDs.synchs[i].trans = CUDD.Function.Times(tmp, sysDDs.synchs[i].trans); } } ComputeRewards(sysDDs); // now, for all model types, transition matrix can be built by summing over all actions // also build transition rewards at the same time CUDD.Ref(sysDDs.ind.trans); trans = sysDDs.ind.trans; int numRewardStructs = modules.rewardStructs.Count; for (int j = 0; j < numRewardStructs; j++) { CUDD.Ref(sysDDs.ind.rewards[j]); transRewards.Add(sysDDs.ind.rewards[j]); } for (int i = 0; i < synchs.Count; i++) { CUDD.Ref(sysDDs.synchs[i].trans); trans = CUDD.Function.Plus(trans, sysDDs.synchs[i].trans); for (int j = 0; j < numRewardStructs; j++) { CUDD.Ref(sysDDs.synchs[i].rewards[j]); transRewards[j] = CUDD.Function.Plus(transRewards[j], sysDDs.synchs[i].rewards[j]); } } // For D/CTMCs, final rewards are scaled by dividing by total prob/rate for each transition // (when individual transition rewards are computed, they are multiplied by individual probs/rates). // Need to do this (for D/CTMCs) because transition prob/rate can be the sum of values from // several different actions; this gives us the "expected" reward for each transition. // (Note, for MDPs, nondeterministic choices are always kept separate so this never occurs.) if (modules.modelType != ModelType.MDP) { int numberOfRewardStructs = modules.rewardStructs.Count; for (int j = 0; j < numberOfRewardStructs; j++) { CUDD.Ref(trans); transRewards[j] = CUDD.Function.Divide(transRewards[j], trans); } } // sysDDs.Deref(); }
/// <summary> /// Calculate state rewards and store in stateRewards /// Transition rewards are prepared and stored in sysDDs /// </summary> /// <param name="sysDDs"></param> private void ComputeRewards(SystemDDs sysDDs) { int numRewardStructs = modules.rewardStructs.Count; //Initialize reward of State and the resulted SystemDDs sysDDs for (int j = 0; j < numRewardStructs; j++) { stateRewards.Add(CUDD.Constant(0)); sysDDs.ind.rewards.Add(CUDD.Constant(0)); for (int i = 0; i < synchs.Count; i++) { sysDDs.synchs[i].rewards.Add(CUDD.Constant(0)); } } // for each reward structure... for (int j = 0; j < numRewardStructs; j++) { // get reward struct RewardStruct rs = modules.rewardStructs[j]; // work through list of items in reward struct foreach (var rewardItem in rs.items) { // translate states predicate and reward expression CUDDNode guard = EncodeExpression(rewardItem.guard); CUDDNode rewards = EncodeExpression(rewardItem.reward); CUDDNode rewardDD; string synch = rewardItem.synch; if (synch == null) { // first case: item corresponds to state rewards // restrict rewards to relevant states rewardDD = CUDD.Function.Times(guard, rewards); // check for negative rewards if (CUDD.FindMin(rewardDD) < 0) { throw new Exception("Reward structure item with guard " + rewardItem.guard + " contains negative rewards"); } // add to state rewards stateRewards[j] = CUDD.Function.Plus(stateRewards[j], rewardDD); } else { // second case: item corresponds to transition rewards //find the corresponding component to update the reward ComponentDDs compDDs; // work out which (if any) action this is for if (synch == string.Empty) { compDDs = sysDDs.ind; } else if (synchs.Contains(synch)) { int k = synchs.IndexOf(synch); compDDs = sysDDs.synchs[k]; } else { throw new Exception("Invalid action name \"" + synch + "\" in reward structure item"); } // identify corresponding transitions // (for dtmcs/ctmcs, keep actual values - need to weight rewards; for mdps just store 0/1) CUDD.Ref(compDDs.trans); rewardDD = (modules.modelType == ModelType.MDP)? (CUDD.Convert.GreaterThan(compDDs.trans, 0)): compDDs.trans; // restrict to relevant states rewardDD = CUDD.Function.Times(rewardDD, guard); // multiply by reward values rewardDD = CUDD.Function.Times(rewardDD, rewards); // check for negative rewards if (CUDD.FindMin(rewardDD) < 0) { throw new Exception("Reward structure item with guard " + rewardItem.guard + " contains negative rewards"); } // add result to rewards compDDs.rewards[j] = CUDD.Function.Plus(compDDs.rewards[j], rewardDD); } } } }