private void EncodeSimulationRel(BDDEncoder encoder, AutomataBDD processBDD, string stateVar) { int stateVarIndex = encoder.model.GetVarIndex(stateVar); CUDDVars rowStateVars = encoder.model.GetRowVars(stateVarIndex); CUDDVars colStateVars = encoder.model.GetColVars(stateVarIndex); CUDDNode result = CUDD.Constant(0); foreach (var pair in mapOldLoc2NewStates) { List <State> statesInLoc = pair.Value; for (int i = 0; i < statesInLoc.Count; i++) { for (int j = 0; j < statesInLoc.Count; j++) { if (ClockValuation.IsLUSimulated(mapNewState2Valuation[statesInLoc[i].ID], mapNewState2Valuation[statesInLoc[j].ID], pair.Key)) { CUDDNode simulated = CUDD.Matrix.SetVectorElement(CUDD.Constant(0), rowStateVars, encoder.stateIndexOfCurrentProcess[statesInLoc[i].ID], 1); CUDDNode simulating = CUDD.Matrix.SetVectorElement(CUDD.Constant(0), colStateVars, encoder.stateIndexOfCurrentProcess[statesInLoc[j].ID], 1); result = CUDD.Function.Or(result, CUDD.Function.And(simulated, simulating)); } } } } processBDD.SimulationRel = result; }
public static CUDDNode ProbBoundedUntil(CUDDNode trans, CUDDVars allRowVars, CUDDVars allColVars, CUDDNode yes, CUDDNode maybe, int bound) { DateTime startTime = DateTime.Now; CUDDNode a, sol, tmp; CUDD.Ref(trans, maybe); a = CUDD.Function.Times(trans, maybe); CUDD.Ref(yes); sol = yes; for (int i = 1; i <= bound; i++) { tmp = CUDD.Matrix.MatrixMultiplyVector(a, sol, allRowVars, allColVars); CUDD.Ref(yes); tmp = CUDD.Function.Maximum(tmp, yes); CUDD.Deref(sol); sol = tmp; } DateTime endTime = DateTime.Now; double runningTime = (endTime - startTime).TotalSeconds; Debug.WriteLine("ProbBoundedUntil: " + bound + " iterations in " + runningTime + " seconds"); // CUDD.Deref(a); return sol; }
public IModel Encode() { //get variable info from ModulesFile varList = new VariableList(modules); //Collect all sync label of all modules synchs = modules.GetAllSynchs().ToList(); AddVars(); //Create Expression Encoder, use the same copy of varList, variableEncoding expressionEncoder = new ExpressionToBDD(varList, variableEncoding); EncodeSystemDef(modules.systemDef); // get rid of any nondet dd variables not needed if (modules.modelType == ModelType.MDP) { CUDDNode tmp = CUDD.GetSupport(trans); tmp = CUDD.Abstract.ThereExists(tmp, allRowVars); tmp = CUDD.Abstract.ThereExists(tmp, allColVars); CUDDVars ddv = new CUDDVars(); while (!tmp.Equals(CUDD.ONE)) { ddv.AddVar(CUDD.Var(tmp.GetIndex())); tmp = tmp.GetThen(); } CUDD.Deref(tmp); allNondetVars.Deref(); allNondetVars = ddv; } init = GetInitState(); // CUDD.Deref(moduleRangeDDs, moduleIdentities, colVarRanges, syncVars, choiceVars); CUDD.Deref(moduleRowVars, moduleColVars, rowVars, colVars, new List <CUDDVars>() { globalRowVars, globalColVars, allSynchVars, allChoiceVars }); IModel result; if (modules.modelType == ModelType.DTMC) { // allNondetVars.Deref(); result = new ProbModel(trans, init, stateRewards, transRewards, allRowVars, allColVars, varList, allRowVarRanges, varIdentities, variableEncoding); } else { result = new NonDetModel(trans, init, stateRewards, transRewards, allRowVars, allColVars, allNondetVars, varList, allRowVarRanges, varIdentities, variableEncoding); } return(result); }
private void GenerateGroundEffect(Dictionary <string, Ground <Predicate> > preGndPredDict) { CUDDVars oldVars = new CUDDVars(); CUDDVars newVars = new CUDDVars(); Dictionary <string, string> abstractParmMap = new Dictionary <string, string>(); //Console.WriteLine(" Ground action constant list count:{0}", gndAction.ConstantList.Count); for (int i = 0; i < ConstantList.Count; i++) { string abstractParm = Container.VariableList[i].Item1; string gndParm = ConstantList[i]; abstractParmMap.Add(abstractParm, gndParm); //Console.WriteLine(" Parameter:{0}, constant:{1}", abstractParm, gndParm); } foreach (var pair in Container.AbstractPredicateDict) { oldVars.AddVar(CUDD.Var(pair.Value.CuddIndex)); List <string> collection = new List <string>(); foreach (var parm in pair.Value.ParameterList) { collection.Add(abstractParmMap[parm]); } string gndPredFullName = VariableContainer.GetFullName(pair.Value.Predicate.Name, collection); Ground <Predicate> gndPred = preGndPredDict[gndPredFullName]; newVars.AddVar(CUDD.Var(gndPred.CuddIndex)); //Console.WriteLine(" old cuddIndex:{0}, new cuddIndex:{1}", pair.Value.CuddIndex, gndPred.CuddIndex); } foreach (var cEffect in Container.Effect) { CUDDNode abstractCondition = cEffect.Item1; CUDDNode gndCondition = CUDD.Variable.SwapVariables(abstractCondition, oldVars, newVars); CUDD.Ref(gndCondition); var gndLiteralList = new List <Tuple <Ground <Predicate>, bool> >(); var abstractLiteralList = cEffect.Item2; foreach (var abstractLiteral in abstractLiteralList) { List <string> collection = new List <string>(); foreach (var parm in abstractLiteral.Item1.ParameterList) { collection.Add(abstractParmMap[parm]); } string gndPredFullName = VariableContainer.GetFullName(abstractLiteral.Item1.Predicate.Name, collection); Ground <Predicate> gndPred = preGndPredDict[gndPredFullName]; var gndLiteral = new Tuple <Ground <Predicate>, bool>(gndPred, abstractLiteral.Item2); gndLiteralList.Add(gndLiteral); } var gndCEffect = new Tuple <CUDDNode, List <Tuple <Ground <Predicate>, bool> > >(gndCondition, gndLiteralList); _effect.Add(gndCEffect); } }
/// <summary> /// Add new not-global variable where row- and column- boolean variable are the same. /// This function is used to add BDD variables to encode event names /// </summary> /// <param name="name"></param> /// <param name="lower"></param> /// <param name="upper"></param> public void AddSingleCopyVar(string name, int lower, int upper) { varList.AddNewVariable(name, lower, upper); int numBits = varList.GetNumberOfBits(name); CUDDNode vr; CUDDVars rowVar = new CUDDVars(); for (int j = 0; j < numBits; j++) { vr = CUDD.Var(numverOfBoolVars++); rowVar.AddVar(vr); } this.rowVars.Add(rowVar); this.colVars.Add(rowVar); this.AllRowVars.AddVars(rowVar); this.AllColVars.AddVars(rowVar); this.AllEventVars.AddVars(rowVar); // used for unchanged variable in transition. CUDDNode identity = (numBits == 0) ? CUDD.Constant(1) : CUDD.Matrix.Identity(rowVar, rowVar); this.varIdentities.Add(identity); // CUDDNode expressionDD = CUDD.MINUS_INFINITY; CUDD.Ref(expressionDD); for (int i = lower; i <= upper; i++) { expressionDD = CUDD.Matrix.SetVectorElement(expressionDD, rowVar, i - lower, i); } this.variableEncoding.Add(expressionDD); }
/// <summary> /// Check whether scc is strong fairness. /// [ REFS: , DEREFS: ] /// </summary> /// <param name="scc"></param> /// <param name="intersection"></param> /// <param name="modelBDD"></param> /// <param name="model"></param> /// <returns></returns> private bool IsWeakFairness(CUDDNode scc, AutomataBDD intersection, AutomataBDD modelBDD, Model model) { CUDD.CUDD.Ref(intersection.transitionBDD); CUDD.CUDD.Ref(scc, scc); List <CUDDNode> transitionInSCC = CUDD.CUDD.Function.And(CUDD.CUDD.Function.And(intersection.transitionBDD, scc), model.SwapRowColVars(scc)); CUDDNode eventHappened = model.GetEventRowInTransition(transitionInSCC); //----------------------------------- CUDD.CUDD.Ref(modelBDD.transitionBDD); CUDD.CUDD.Ref(scc); List <CUDDNode> transitionFromSCC = CUDD.CUDD.Function.And(modelBDD.transitionBDD, scc); CUDD.CUDD.Ref(transitionFromSCC); CUDDNode eventEnabled = model.GetEventRowInTransition(transitionFromSCC); //Get all the combination of state in scc and event CUDD.CUDD.Ref(scc, eventEnabled); CUDDNode complementTransitionFromSCC = CUDD.CUDD.Function.And(scc, model.SwapRowColVars(eventEnabled)); // CUDDVars varsTemp = new CUDDVars(); varsTemp.AddVars(model.AllColVars); varsTemp.RemoveVars(model.GetEventColVars()); //Get the source state (in scc) and event transitionFromSCC = CUDD.CUDD.Abstract.ThereExists(transitionFromSCC, varsTemp); complementTransitionFromSCC = CUDD.CUDD.Function.Different(complementTransitionFromSCC, CUDD.CUDD.Function.Or(transitionFromSCC)); CUDDNode eventNotAllEnabled = model.GetEventRowInTransition(new List <CUDDNode> { complementTransitionFromSCC }); CUDDNode eventAllEnabled = CUDD.CUDD.Function.Different(eventEnabled, eventNotAllEnabled); bool isWeakFairness = CUDD.CUDD.IsSubSet(eventHappened, eventAllEnabled); if (isWeakFairness) { //Must assign this.eventMushHappen to eventHappened to make sure that all enabled events will happen. //In some case though the eventAllEnable is empty but if this.evenMustHappen = eventAllEnable, the scc is not restricted //and a small part of this scc is explored, so in this small part, the eventAllEnable may be not empty. CUDD.CUDD.Ref(eventHappened); CUDD.CUDD.Deref(this.eventMustHappen); this.eventMustHappen = eventHappened; CUDD.CUDD.Ref(scc); CUDD.CUDD.Deref(this.scc); this.scc = scc; } // CUDD.CUDD.Deref(eventHappened, eventAllEnabled); return(isWeakFairness); }
public static CUDDNode NondetUntil(CUDDNode trans, CUDDNode nondetMask, CUDDVars allRowVars, CUDDVars allColVars, CUDDVars nondetVars, CUDDNode yes, CUDDNode maybe, bool min) { DateTime startTime = DateTime.Now; int numberOfIterations = 0; CUDDNode a, sol, tmp; CUDD.Ref(trans, maybe); a = CUDD.Function.Times(trans, maybe); CUDD.Ref(yes); sol = yes; while (true) { numberOfIterations++; tmp = CUDD.Matrix.MatrixMultiplyVector(a, sol, allRowVars, allColVars); if (min) { CUDD.Ref(nondetMask); tmp = CUDD.Function.Maximum(tmp, nondetMask); tmp = CUDD.Abstract.MinAbstract(tmp, nondetVars); } else { tmp = CUDD.Abstract.MaxAbstract(tmp, nondetVars); } CUDD.Ref(yes); tmp = CUDD.Function.Maximum(tmp, yes); //check convergence if (CUDD.IsEqual(tmp, sol)) { CUDD.Deref(tmp); break; } CUDD.Deref(sol); sol = tmp; } DateTime endTime = DateTime.Now; double runningTime = (endTime - startTime).TotalSeconds; Debug.WriteLine("NondetUntil: " + numberOfIterations + " iterations in " + runningTime + " seconds"); // CUDD.Deref(a); return(sol); }
/// <summary> /// Return the rol-vars vector of the product of matrix and vector /// [ REFS: 'result', DEREFS: '' ] /// </summary> /// <param name="matrix">Matrix of rol * col vars</param> /// <param name="vector">Vector of rol vars</param> /// <returns></returns> public static CUDDNode MatrixMultiplyVector(CUDDNode matrix, CUDDNode vector, CUDDVars allRowVars, CUDDVars allColVars) { //Return matrix * vector CUDD.Ref(vector); CUDDNode temp = Variable.SwapVariables(vector, allRowVars, allColVars); CUDD.Ref(matrix); CUDDNode result = MatrixMultiply(matrix, temp, allColVars, BOULDER); return result; }
/// <summary> /// Return state having probability 1 of b1 U b2 /// [ REFS: 'result', DEREFS: ] /// </summary> /// <param name="trans01"></param> /// <param name="reach"></param> /// <param name="allRowVars"></param> /// <param name="allColVars"></param> /// <param name="b1"></param> /// <param name="b2"></param> /// <param name="no"></param> /// <returns></returns> public static CUDDNode Prob1(CUDDNode trans01, CUDDNode reach, CUDDVars allRowVars, CUDDVars allColVars, CUDDNode b1, CUDDNode b2, CUDDNode no) { DateTime startTime = DateTime.Now; int numberOfIterations = 0; CUDD.Ref(no); CUDDNode sol = no; while (true) { numberOfIterations++; CUDD.Ref(sol); CUDDNode tmp = CUDD.Variable.SwapVariables(sol, allRowVars, allColVars); CUDD.Ref(trans01); tmp = CUDD.Function.And(tmp, trans01); tmp = CUDD.Abstract.ThereExists(tmp, allColVars); CUDD.Ref(b1); tmp = CUDD.Function.And(b1, tmp); CUDD.Ref(b2); tmp = CUDD.Function.And(CUDD.Function.Not(b2), tmp); CUDD.Ref(no); tmp = CUDD.Function.Or(no, tmp); if (tmp.Equals(sol)) { CUDD.Deref(tmp); break; } CUDD.Deref(sol); sol = tmp; } CUDD.Ref(reach); sol = CUDD.Function.And(reach, CUDD.Function.Not(sol)); DateTime endTime = DateTime.Now; double runningTime = (endTime - startTime).TotalSeconds; Debug.WriteLine("Prob1: " + numberOfIterations + " iterations in " + runningTime + " seconds"); return(sol); }
protected ExpressionToBDD(ProbModel model) { this.allRowVars = model.allRowVars; this.allColVars = model.allColVars; this.allRowVarRanges = model.allRowVarRanges; this.varIdentities = model.varIdentities; this.varList = model.varList; this.varEncodings = model.varEncodings; this.trans = model.trans; this.start = model.start; this.stateRewards = model.stateRewards; this.transRewards = model.transRewards; }
public NondetModelChecker(NonDetModel model) : base(model) { allNondetVars = model.allNondetVars; FilterStates(); CUDD.Ref(trans01, reach); nondetMask = CUDD.Function.And(CUDD.Function.Not(CUDD.Abstract.ThereExists(trans01, allColVars)), reach); Debug.WriteLine("States: " + CUDD.GetNumMinterms(reach, allRowVars.GetNumVars()) + " (" + CUDD.GetNumMinterms(start, allRowVars.GetNumVars()) + " initial)"); Debug.WriteLine("Transitions: " + CUDD.GetNumMinterms(trans01, allRowVars.GetNumVars() * 2 + allNondetVars.GetNumVars())); Debug.WriteLine("Transition matrix: " + CUDD.Print.GetInfoString(trans, allRowVars.GetNumVars() * 2 + allNondetVars.GetNumVars()) + ", vars: " + allRowVars.GetNumVars() + "r/" + allColVars.GetNumVars() + "c/" + allNondetVars.GetNumVars() + "nd"); }
public ProbModel(CUDDNode trans, CUDDNode start, List <CUDDNode> stateRewards, List <CUDDNode> transRewards, CUDDVars allRowVars, CUDDVars allColVars, VariableList varList, CUDDNode allRowVarRanges, List <CUDDNode> varIdentities, List <CUDDNode> varEncodings) { this.trans = trans; this.start = start; this.stateRewards = stateRewards; this.transRewards = transRewards; this.allRowVars = allRowVars; this.allColVars = allColVars; this.varList = varList; this.allRowVarRanges = allRowVarRanges; this.varIdentities = varIdentities; this.varEncodings = varEncodings; }
/// <summary> /// Add new local variable /// </summary> /// <param name="name"></param> /// <param name="lower"></param> /// <param name="upper"></param> public void AddLocalVar(string name, int lower, int upper) { varList.AddNewVariable(name, lower, upper); int numBits = varList.GetNumberOfBits(name); CUDDNode vr, vc; CUDDVars rowVar = new CUDDVars(); CUDDVars colVar = new CUDDVars(); for (int j = 0; j < numBits; j++) { vr = CUDD.Var(numverOfBoolVars++); vc = CUDD.Var(numverOfBoolVars++); rowVar.AddVar(vr); colVar.AddVar(vc); } this.rowVars.Add(rowVar); this.colVars.Add(colVar); this.AllRowVars.AddVars(rowVar); this.AllRowVarsExceptSingleCopy.AddVars(rowVar); this.AllColVars.AddVars(colVar); // used for unchanged variable in transition. CUDDNode identity = CUDD.Constant(0); for (int i = lower; i <= upper; i++) { identity = CUDD.Matrix.SetMatrixElement(identity, rowVar, colVar, i - lower, i - lower, 1); } this.varIdentities.Add(identity); // CUDDNode expressionDD = CUDD.MINUS_INFINITY; CUDD.Ref(expressionDD); for (int i = lower; i <= upper; i++) { expressionDD = CUDD.Matrix.SetVectorElement(expressionDD, rowVar, i - lower, i); } this.variableEncoding.Add(expressionDD); // CUDD.Ref(identity); allRowVarRanges = CUDD.Function.And(allRowVarRanges, CUDD.Abstract.ThereExists(identity, colVar)); CUDD.Ref(identity); colVarRanges.Add(CUDD.Abstract.ThereExists(identity, rowVar)); }
private void UpdateKnowledge(EventModel eventModel) { //Console.WriteLine("Enter update knowledge"); //CUDD.Ref(eventModel.KnowPrecondition); //Console.WriteLine("After ref know precondition"); //CUDDNode knowledgeWithPre = CUDD.Function.And(Knowledge, eventModel.KnowPrecondition); CUDD.Ref(eventModel.KnowPartialSsa); //Console.WriteLine("After ref know partial ssa"); CUDDNode knowledgeWithPssa = CUDD.Function.And(Knowledge, eventModel.KnowPartialSsa); //Console.WriteLine("After get knowledge with pre and partial ssa"); if (eventModel.KnowAffectedPredSet.Count != 0) { CUDDVars oldVars = new CUDDVars(); CUDDVars newVars = new CUDDVars(); foreach (var predicate in eventModel.KnowAffectedPredSet) { CUDDNode trueRestrictBy = CUDD.Var(predicate.PreviousCuddIndex); CUDD.Ref(trueRestrictBy); CUDD.Ref(knowledgeWithPssa); CUDDNode trueNode = CUDD.Function.Restrict(knowledgeWithPssa, trueRestrictBy); CUDDNode falseRestrictBy = CUDD.Function.Not(trueRestrictBy); CUDDNode falseNode = CUDD.Function.Restrict(knowledgeWithPssa, falseRestrictBy); knowledgeWithPssa = CUDD.Function.Or(trueNode, falseNode); oldVars.AddVar(CUDD.Var(predicate.SuccessiveCuddIndex)); newVars.AddVar(CUDD.Var(predicate.PreviousCuddIndex)); } Knowledge = CUDD.Variable.SwapVariables(knowledgeWithPssa, oldVars, newVars); oldVars.Deref(); newVars.Deref(); } else { Knowledge = knowledgeWithPssa; } //Console.WriteLine("Whether knowledge is equal to false: {0}", Knowledge.Equals(CUDD.ZERO)); //Console.WriteLine("Finish!"); }
/// <summary> /// Get the column variable value (after transition) from BDD configuration. This value must be added with Lowerbound value. See the Variable Expression /// implementation /// [ REFS: '', DEREFS: ''] /// </summary> public int GetColVarValue(CUDDNode currentStateDD, string variableName) { CUDDVars notSelectedVariables = new CUDDVars(); notSelectedVariables.AddVars(this.AllColVars); notSelectedVariables.RemoveVars(this.GetColVars(variableName)); CUDD.Ref(currentStateDD); CUDDNode selectedEventDD = CUDD.Abstract.ThereExists(currentStateDD, notSelectedVariables); int selectedEvent = CUDD.MinTermToInt(selectedEventDD, this.GetColVars(variableName)); CUDD.Deref(selectedEventDD); // selectedEvent += this.GetVarLowerBound(variableName); return(selectedEvent); }
/// <summary> /// Only find event from period[1] /// </summary> /// <param name="period"></param> /// <returns></returns> private CUDDNode GetEventInStates(Model model) { CUDDNode result = CUDD.CUDD.Constant(0); if (period.Count > 1) { CUDDVars temp = new CUDDVars(); temp.AddVars(model.AllRowVars); temp.RemoveVars(model.GetEventRowVars()); for (int i = 1; i < period.Count; i++) { CUDD.CUDD.Ref(period[i]); result = CUDD.CUDD.Function.Or(result, CUDD.CUDD.Abstract.ThereExists(period[i], temp)); } } return(result); }
/// <summary> /// Return variable expression /// </summary> public override ExpressionBDDEncoding TranslateIntExpToBDD(Model model) { ExpressionBDDEncoding result = new ExpressionBDDEncoding(); result.GuardDDs.Add(CUDD.Constant(1)); int variableIndex = model.GetVarIndex(this.expressionID); CUDDNode varDD = model.variableEncoding[variableIndex]; CUDD.Ref(varDD); CUDDVars rowVars = model.GetRowVars(variableIndex); CUDDVars colVars = model.GetColVars(variableIndex); varDD = CUDD.Variable.SwapVariables(varDD, rowVars, colVars); result.ExpressionDDs.Add(varDD); return(result); }
public static CUDDNode ProbUntil(CUDDNode trans, CUDDNode reach, CUDDVars allRowVars, CUDDVars allColVars, CUDDNode yes, CUDDNode maybe) { CUDD.Ref(trans, maybe); CUDDNode a = CUDD.Function.Times(trans, maybe); CUDDNode tmp = CUDD.Matrix.Identity(allRowVars, allColVars); CUDD.Ref(reach); tmp = CUDD.Function.And(tmp, reach); a = CUDD.Function.Minus(tmp, a); CUDD.Ref(yes); CUDDNode b = yes; CUDDNode sol = Jacobi(a, b, b, reach, allRowVars, allColVars, 1); CUDD.Deref(a, b); return sol; }
public static CUDDNode ProbInstReward(CUDDNode trans, CUDDNode stateReward, CUDDVars allRowVars, CUDDVars allColVars, int bound) { DateTime startTime = DateTime.Now; // initial solution is the state rewards CUDD.Ref(stateReward); CUDDNode sol = stateReward; for (int iters = 0; iters < bound; iters++) { CUDDNode tmp = CUDD.Matrix.MatrixMultiplyVector(trans, sol, allRowVars, allColVars); CUDD.Deref(sol); sol = tmp; } DateTime endTime = DateTime.Now; double runningTime = (endTime - startTime).TotalSeconds; Debug.WriteLine("ProbInstReward: " + bound + " iterations in " + runningTime + " seconds"); return sol; }
private void GenerateGroundPrecondition(Dictionary <string, Ground <Predicate> > preGndPredDict) { CUDDVars oldVars = new CUDDVars(); CUDDVars newVars = new CUDDVars(); Dictionary <string, string> abstractParmMap = new Dictionary <string, string>(); //Console.WriteLine(" Ground action constant list count:{0}", gndAction.ConstantList.Count); for (int i = 0; i < ConstantList.Count; i++) { string abstractParm = Container.VariableList[i].Item1; string gndParm = ConstantList[i]; abstractParmMap.Add(abstractParm, gndParm); //Console.WriteLine(" Parameter:{0}, constant:{1}", abstractParm, gndParm); } foreach (var pair in Container.AbstractPredicateDict) { oldVars.AddVar(CUDD.Var(pair.Value.CuddIndex)); List <string> collection = new List <string>(); foreach (var parm in pair.Value.ParameterList) { collection.Add(abstractParmMap[parm]); } Ground <Predicate> gndPred = new Ground <Predicate>(pair.Value.Predicate, collection); gndPred = preGndPredDict[gndPred.ToString()]; newVars.AddVar(CUDD.Var(gndPred.CuddIndex)); } CUDDNode abstractPre = Container.Precondition; Precondition = CUDD.Variable.SwapVariables(abstractPre, oldVars, newVars); //Console.WriteLine(" Ground precondition:"); //CUDD.Print.PrintMinterm(gndAction.Precondition); //CUDDNode abstractEff = gndAction.VariableContainer.Effect; //gndAction.VariableContainer.Effect = CUDD.Variable.SwapVariables(abstractEff, oldVars, newVars); }
private void UpdateBelief(CUDDNode partialSsa, HashSet <Predicate> affectedPredSet) { //CUDD.Ref(precondition); //CUDDNode beliefWithPre = CUDD.Function.And(Belief, precondition); CUDD.Ref(partialSsa); CUDDNode beliefWithPssa = CUDD.Function.And(Belief, partialSsa); if (affectedPredSet.Count != 0) { CUDDVars oldVars = new CUDDVars(); CUDDVars newVars = new CUDDVars(); foreach (var predicate in affectedPredSet) { CUDDNode trueRestrictBy = CUDD.Var(predicate.PreviousCuddIndex); CUDD.Ref(trueRestrictBy); CUDD.Ref(beliefWithPssa); CUDDNode trueNode = CUDD.Function.Restrict(beliefWithPssa, trueRestrictBy); CUDDNode falseRestrictBy = CUDD.Function.Not(trueRestrictBy); CUDDNode falseNode = CUDD.Function.Restrict(beliefWithPssa, falseRestrictBy); beliefWithPssa = CUDD.Function.Or(trueNode, falseNode); oldVars.AddVar(CUDD.Var(predicate.SuccessiveCuddIndex)); newVars.AddVar(CUDD.Var(predicate.PreviousCuddIndex)); } Belief = CUDD.Variable.SwapVariables(beliefWithPssa, oldVars, newVars); oldVars.Deref(); newVars.Deref(); } else { Belief = beliefWithPssa; } //Console.WriteLine("Whether belief is equal to false: {0}", Belief.Equals(CUDD.ZERO)); //Console.WriteLine("Finish!"); }
public static CUDDNode NondetInstReward(CUDDNode trans, CUDDNode stateReward, CUDDNode nondetMask, CUDDVars allRowVars, CUDDVars allColVars, CUDDVars nondetVars, int bound, bool min, CUDDNode init) { DateTime startTime = DateTime.Now; CUDDNode newNondetMask, sol, tmp; CUDD.Ref(nondetMask); newNondetMask = CUDD.Function.ITE(nondetMask, CUDD.PlusInfinity(), CUDD.Constant(0)); CUDD.Ref(stateReward); sol = stateReward; for (int i = 0; i < bound; i++) { tmp = CUDD.Matrix.MatrixMultiplyVector(trans, sol, allRowVars, allColVars); if (min) { CUDD.Ref(newNondetMask); tmp = CUDD.Function.Maximum(tmp, newNondetMask); tmp = CUDD.Abstract.MinAbstract(tmp, nondetVars); } else { tmp = CUDD.Abstract.MaxAbstract(tmp, nondetVars); } // CUDD.Deref(sol); sol = tmp; } DateTime endTime = DateTime.Now; double runningTime = (endTime - startTime).TotalSeconds; Debug.WriteLine("NondetInstReward: " + bound + " iterations in " + runningTime + " seconds"); // CUDD.Deref(newNondetMask); return(sol); }
/// <summary> /// Set the value of i.th element in vector. i is allowed to be negative. -1 is the last element. /// Note that this is a function, not a procedure /// [ REFS: 'result', DEREFS: 'dd' ] /// </summary> public static CUDDNode SetVectorElement(CUDDNode dd, CUDDVars vars, int index, double value) { return new CUDDNode(PlatformInvoke.DD_SetVectorElement(manager, dd.Ptr, vars.GetArrayPointer(), vars.GetNumVars(), index, value)); }
public static CUDDNode NondetBoundedUntil(CUDDNode trans, CUDDNode nondetMask, CUDDVars allRowVars, CUDDVars allColVars, CUDDVars nondetVars, CUDDNode yes, CUDDNode maybe, int bound, bool min) { DateTime startTime = DateTime.Now; CUDDNode a, sol, tmp; CUDD.Ref(trans, maybe); a = CUDD.Function.Times(trans, maybe); CUDD.Ref(yes); sol = yes; for (int i = 0; i < bound; i++) { tmp = CUDD.Matrix.MatrixMultiplyVector(a, sol, allRowVars, allColVars); if (min) { CUDD.Ref(nondetMask); tmp = CUDD.Function.Maximum(tmp, nondetMask); tmp = CUDD.Abstract.MinAbstract(tmp, nondetVars); } else { tmp = CUDD.Abstract.MaxAbstract(tmp, nondetVars); } CUDD.Ref(yes); tmp = CUDD.Function.Maximum(tmp, yes); CUDD.Deref(sol); sol = tmp; } DateTime endTime = DateTime.Now; double runningTime = (endTime - startTime).TotalSeconds; Debug.WriteLine("NondetBoundedUntil: " + bound + " iterations in " + runningTime + " seconds"); // CUDD.Deref(a); return(sol); }
/// <summary> /// Return Pmin(phi1 U phi2) = 1 /// </summary> /// <param name="trans01"></param> /// <param name="reach"></param> /// <param name="nondetMask"></param> /// <param name="allRowVars"></param> /// <param name="allColVars"></param> /// <param name="nondetVar"></param> /// <param name="no"></param> /// <param name="b2"></param> /// <returns></returns> public static CUDDNode Prob1A(CUDDNode trans01, CUDDNode reach, CUDDNode nondetMask, CUDDVars allRowVars, CUDDVars allColVars, CUDDVars nondetVar, CUDDNode no, CUDDNode b2) { DateTime startTime = DateTime.Now; int numberOfIterations = 0; CUDD.Ref(reach, no); CUDDNode notNo = CUDD.Function.And(reach, CUDD.Function.Not(no)); CUDD.Ref(b2, notNo); CUDDNode sol = CUDD.Function.Or(b2, notNo); while (true) { numberOfIterations++; CUDD.Ref(sol); CUDDNode tmp = CUDD.Variable.SwapVariables(sol, allRowVars, allColVars); CUDD.Ref(trans01); tmp = CUDD.Abstract.ForAll(CUDD.Function.Implies(trans01, tmp), allColVars); CUDD.Ref(nondetMask); tmp = CUDD.Function.Or(tmp, nondetMask); tmp = CUDD.Abstract.ForAll(tmp, nondetVar); CUDD.Ref(notNo); tmp = CUDD.Function.And(notNo, tmp); CUDD.Ref(b2); tmp = CUDD.Function.Or(b2, tmp); if (tmp.Equals(sol)) { CUDD.Deref(tmp); break; } CUDD.Deref(sol); sol = tmp; } DateTime endTime = DateTime.Now; double runningTime = (endTime - startTime).TotalSeconds; Debug.WriteLine("Prob1A: " + numberOfIterations + " iterations in " + runningTime + " seconds"); // CUDD.Deref(notNo); return(sol); }
/// <summary> /// return Pmax(b1 U b2) = 1 /// </summary> /// <param name="trans01"></param> /// <param name="reach"></param> /// <param name="allRowVars"></param> /// <param name="allColVars"></param> /// <param name="nondetVars"></param> /// <param name="b1"></param> /// <param name="b2"></param> /// <param name="no"></param> /// <returns></returns> public static CUDDNode Prob1E(CUDDNode trans01, CUDDNode reach, CUDDVars allRowVars, CUDDVars allColVars, CUDDVars nondetVars, CUDDNode b1, CUDDNode b2, CUDDNode no) { DateTime startTime = DateTime.Now; int numberOfIterations = 0; CUDD.Ref(reach, no); CUDDNode u = CUDD.Function.And(reach, CUDD.Function.Not(no)); bool uDone = false; while (!uDone) { CUDDNode v = CUDD.Constant(0); bool vDone = false; while (!vDone) { numberOfIterations++; CUDD.Ref(u); CUDDNode tmp = CUDD.Variable.SwapVariables(u, allRowVars, allColVars); CUDD.Ref(trans01); tmp = CUDD.Abstract.ForAll(CUDD.Function.Implies(trans01, tmp), allColVars); CUDD.Ref(v); CUDDNode tmp2 = CUDD.Variable.SwapVariables(v, allRowVars, allColVars); CUDD.Ref(trans01); tmp2 = CUDD.Abstract.ThereExists(CUDD.Function.And(tmp2, trans01), allColVars); tmp = CUDD.Function.And(tmp, tmp2); tmp = CUDD.Abstract.ThereExists(tmp, nondetVars); CUDD.Ref(b1); tmp = CUDD.Function.And(b1, tmp); CUDD.Ref(b2); tmp = CUDD.Function.Or(b2, tmp); if (tmp.Equals(v)) { vDone = true; } CUDD.Deref(v); v = tmp; } if (v == u) { uDone = true; } CUDD.Deref(u); u = v; } DateTime endTime = DateTime.Now; double runningTime = (endTime - startTime).TotalSeconds; Debug.WriteLine("Prob1E: " + numberOfIterations + " iterations in " + runningTime + " seconds"); return(u); }
public NonDetModel(CUDDNode trans, CUDDNode start, List <CUDDNode> stateRewards, List <CUDDNode> transReward, CUDDVars allRowVars, CUDDVars allColVars, CUDDVars allNondetVars, VariableList varList, CUDDNode allRowVarRanges, List <CUDDNode> varIdentities, List <CUDDNode> variableEncodings) : base(trans, start, stateRewards, transReward, allRowVars, allColVars, varList, allRowVarRanges, varIdentities, variableEncodings) { this.allNondetVars = allNondetVars; }
/// <summary> /// Solve the linear equation system Ax = b with Jacobi /// </summary> /// <param name="a"></param> /// <param name="b"></param> /// <param name="init">initial solution</param> /// <param name="reach"></param> /// <param name="allRowVars"></param> /// <param name="allColVars"></param> /// <param name="omega">jor parameter</param> /// <returns></returns> public static CUDDNode Jacobi(CUDDNode a, CUDDNode b, CUDDNode init, CUDDNode reach, CUDDVars allRowVars, CUDDVars allColVars, double omega) { DateTime startTime = DateTime.Now; int numberOfIterations = 0; CUDDNode id = CUDD.Matrix.Identity(allRowVars, allColVars); CUDD.Ref(reach); id = CUDD.Function.And(id, reach); CUDD.Ref(id, a); CUDDNode diags = CUDD.Function.Times(id, a); diags = CUDD.Abstract.SumAbstract(diags, allColVars); // CUDD.Ref(id, a); CUDDNode newA = CUDD.Function.ITE(id, CUDD.Constant(0), a); newA = CUDD.Function.Times(CUDD.Constant(-1), newA); // divide a,b by diagonal CUDD.Ref(diags); newA = CUDD.Function.Divide(newA, diags); CUDD.Ref(b, diags); CUDDNode newB = CUDD.Function.Divide(b, diags); // print out some memory usage Debug.WriteLine("Iteration matrix MTBDD... [nodes = " + CUDD.GetNumNodes(newA) + "]"); Debug.WriteLine("Diagonals MTBDD... [nodes = " + CUDD.GetNumNodes(diags) + "]"); CUDD.Ref(init); CUDDNode sol = init; while(true) { numberOfIterations++; CUDDNode tmp = CUDD.Matrix.MatrixMultiplyVector(newA, sol, allRowVars, allColVars); CUDD.Ref(newB); tmp = CUDD.Function.Plus(tmp, newB); if(omega != 1) { tmp = CUDD.Function.Times(tmp, CUDD.Constant(omega)); CUDD.Ref(sol); tmp = CUDD.Function.Plus(tmp, CUDD.Function.Times(sol, CUDD.Constant(1 - omega))); } if(CUDD.IsEqual(tmp, sol)) { CUDD.Deref(tmp); break; } CUDD.Deref(sol); sol = tmp; } CUDD.Deref(id, diags, newA, newB); DateTime endTime = DateTime.Now; double runningTime = (endTime - startTime).TotalSeconds; Debug.WriteLine("Jacobi: " + numberOfIterations + " iterations in " + runningTime + " seconds"); return sol; }
/// <summary> /// Sets element in matrix dd and return value. /// Note that this is a function, not a procedure /// [ REFS: 'result', DEREFS: 'dd' ] /// </summary> public static CUDDNode SetMatrixElement(CUDDNode dd, CUDDVars rVars, CUDDVars cVars, int rIndex, int cIndex, double value) { return new CUDDNode(PlatformInvoke.DD_SetMatrixElement(manager, dd.Ptr, rVars.GetArrayPointer(), rVars.GetNumVars(), cVars.GetArrayPointer(), cVars.GetNumVars(), rIndex, cIndex, value)); }
public static CUDDNode NondetReachReward(CUDDNode trans, CUDDNode reach, CUDDNode stateReward, CUDDNode transReward, CUDDNode nondetMask, CUDDVars allRowVars, CUDDVars allColVars, CUDDVars nondetVars, CUDDNode infReward, CUDDNode maybeReward, bool min) { DateTime startTime = DateTime.Now; int numberOfIterations = 0; CUDDNode a, allReward, newNondetMask, sol, tmp; // filter out rows (goal states and infinity states) from matrix CUDD.Ref(trans, maybeReward); a = CUDD.Function.Times(trans, maybeReward); // also remove goal and infinity states from state rewards vector CUDD.Ref(stateReward, maybeReward); CUDDNode tempStateReward = CUDD.Function.Times(stateReward, maybeReward); // multiply transition rewards by transition probs and sum rows // (note also filters out unwanted states at the same time) CUDD.Ref(transReward, a); CUDDNode tempTransReward = CUDD.Function.Times(transReward, a); tempTransReward = CUDD.Abstract.SumAbstract(tempTransReward, allColVars); // combine state and transition rewards allReward = CUDD.Function.Plus(tempStateReward, tempTransReward); // need to change mask because rewards are not necessarily in the range 0..1 CUDD.Ref(nondetMask); newNondetMask = CUDD.Function.ITE(nondetMask, CUDD.PlusInfinity(), CUDD.Constant(0)); // initial solution is infinity in 'inf' states, zero elsewhere // note: ok to do this because cudd matrix-multiply (and other ops) // treat 0 * inf as 0, unlike in IEEE 754 rules CUDD.Ref(infReward); sol = CUDD.Function.ITE(infReward, CUDD.PlusInfinity(), CUDD.Constant(0)); while (true) { numberOfIterations++; tmp = CUDD.Matrix.MatrixMultiplyVector(a, sol, allRowVars, allColVars); // add rewards CUDD.Ref(allReward); tmp = CUDD.Function.Plus(tmp, allReward); if (min) { CUDD.Ref(newNondetMask); tmp = CUDD.Function.Maximum(tmp, newNondetMask); tmp = CUDD.Abstract.MinAbstract(tmp, nondetVars); } else { tmp = CUDD.Abstract.MaxAbstract(tmp, nondetVars); } CUDD.Ref(infReward); tmp = CUDD.Function.ITE(infReward, CUDD.PlusInfinity(), tmp); if (CUDD.IsEqual(tmp, sol)) { CUDD.Deref(tmp); break; } CUDD.Deref(sol); sol = tmp; } DateTime endTime = DateTime.Now; double runningTime = (endTime - startTime).TotalSeconds; Debug.WriteLine("NondetReachReward: " + numberOfIterations + " iterations in " + runningTime + " seconds"); // CUDD.Deref(a, allReward, newNondetMask); return(sol); }
public static CUDDNode ProbCumulReward(CUDDNode trans, CUDDNode stateReward, CUDDNode transReward, CUDDVars allRowVars, CUDDVars allColVars, int bound) { DateTime startTime = DateTime.Now; // multiply transition rewards by transition probs and sum rows // then combine state and transition rewards and put in a vector CUDD.Ref(transReward, trans); CUDDNode allReward = CUDD.Function.Times(transReward, trans); allReward = CUDD.Abstract.SumAbstract(allReward, allColVars); CUDD.Ref(stateReward); allReward = CUDD.Function.Plus(stateReward, allReward); // initial solution is zero CUDDNode sol = CUDD.Constant(0); for (int i = 0; i < bound; i++) { CUDDNode tmp = CUDD.Matrix.MatrixMultiplyVector(trans, sol, allRowVars, allColVars); // add in (combined state and transition) rewards CUDD.Ref(allReward); tmp = CUDD.Function.Plus(tmp, allReward); CUDD.Deref(sol); sol = tmp; } // CUDD.Deref(allReward); DateTime endTime = DateTime.Now; double runningTime = (endTime - startTime).TotalSeconds; Debug.WriteLine("ProbCumulReward: " + bound + " iterations in " + runningTime + " seconds"); // return sol; }
/// <summary> /// Returns transpose of matrix dd /// [ REFS: 'result', DEREFS: 'dd' ] /// </summary> public static CUDDNode Transpose(CUDDNode dd, CUDDVars rVars, CUDDVars cVars) { return new CUDDNode(PlatformInvoke.DD_Transpose(manager, dd.Ptr, rVars.GetArrayPointer(), cVars.GetArrayPointer(), rVars.GetNumVars())); }
/// <summary> /// [ REFS: 'result', DEREFS: 'guardDDs, commandDDs' ] /// </summary> /// <param name="guardDDs"></param> /// <param name="commandDDs"></param> /// <param name="currentAvailStartBit"></param> /// <returns></returns> private ComponentDDs CombineNondetCommands(List <CUDDNode> guardDDs, List <CUDDNode> commandDDs, int currentAvailStartBit) { ComponentDDs compDDs; int i, j, maxChoices, numDDChoiceVarsUsed; CUDDNode covered, transDD, overlaps, guardHasIChoices, tmp; // create object to return result compDDs = new ComponentDDs(); // use 'transDD' to build up MTBDD for transitions transDD = CUDD.Constant(0); // use 'covered' to track states covered by guards covered = CUDD.Constant(0); // find overlaps in guards by adding them all up overlaps = CUDD.Constant(0); for (i = 0; i < guardDDs.Count; i++) { CUDD.Ref(guardDDs[i]); overlaps = CUDD.Function.Plus(overlaps, guardDDs[i]); // compute bdd of all guards at same time CUDD.Ref(guardDDs[i]); covered = CUDD.Function.Or(covered, guardDDs[i]); } // find the max number of overlaps // (i.e. max number of nondet. choices) maxChoices = (int)Math.Round(CUDD.FindMax(overlaps)); // if all the guards were false, we're done already if (maxChoices == 0) { compDDs.guards = covered; compDDs.trans = transDD; compDDs.min = currentAvailStartBit; compDDs.max = currentAvailStartBit; CUDD.Deref(overlaps); CUDD.Deref(guardDDs, commandDDs); return(compDDs); } // likewise, if there are no overlaps, it's also pretty easy if (maxChoices == 1) { // add up dds for all commands for (i = 0; i < guardDDs.Count; i++) { // add up transitions CUDD.Ref(commandDDs[i]); transDD = CUDD.Function.Plus(transDD, commandDDs[i]); } compDDs.guards = covered; compDDs.trans = transDD; compDDs.min = currentAvailStartBit; compDDs.max = currentAvailStartBit; CUDD.Deref(overlaps); CUDD.Deref(guardDDs, commandDDs); return(compDDs); } // otherwise, it's a bit more complicated... // first, calculate how many dd vars will be needed //the indexes of these bits are: (currentLastBitForChoice + 1), (currentLastBitForChoice + 2), ... numDDChoiceVarsUsed = (int)Math.Ceiling(Math.Log(maxChoices, 2)); // select the variables we will use and put them in a JDDVars if (currentAvailStartBit + numDDChoiceVarsUsed - 1 >= choiceVars.Count) { throw new Exception("Insufficient BDD variables allocated for nondeterminism - please report this as a bug. Thank you."); } CUDDVars varForThisChoice = new CUDDVars(); for (i = 0; i < numDDChoiceVarsUsed; i++) { varForThisChoice.AddVar(choiceVars[currentAvailStartBit + i]); } // for each i (i = 1 ... max number of nondet. choices) for (i = 1; i <= maxChoices; i++) { // find sections of state space // which have exactly i nondet. choices in this module CUDD.Ref(overlaps); guardHasIChoices = CUDD.Convert.Equals(overlaps, i); // if there aren't any for this i, skip the iteration if (guardHasIChoices.Equals(CUDD.ZERO)) { CUDD.Deref(guardHasIChoices); continue; } //store guards satisfying the guardHasIChoices, and classify them List <CUDDNode> satisfiedGuards = new List <CUDDNode>(); //store the current number of commands satisfying the guard of the corresponding guard List <int> numberOfChoicesAdded = new List <int>(); // go thru each command of the module... for (j = 0; j < guardDDs.Count; j++) { // see if this command's guard overlaps with 'guardHasIChoices' CUDD.Ref(guardDDs[j], guardHasIChoices); tmp = CUDD.Function.And(guardDDs[j], guardHasIChoices); // if it does... if (!tmp.Equals(CUDD.ZERO)) { //find guard Index int guardIndex = -1; int choiceIndexForThisCommand = 0; for (int k = 0; k < satisfiedGuards.Count; k++) { if (satisfiedGuards[k].Equals(tmp)) { guardIndex = k; break; } } //if guard exists, then use the index from numberOfChoicesAdded, and increase it if (guardIndex >= 0) { choiceIndexForThisCommand = numberOfChoicesAdded[guardIndex]; numberOfChoicesAdded[guardIndex]++; } else { //if not exists, satisfiedGuards, numberOfChoicesAdded satisfiedGuards.Add(tmp); numberOfChoicesAdded.Add(1); } CUDD.Ref(commandDDs[j]); tmp = CUDD.Function.Times(tmp, commandDDs[j]); CUDDNode choiceIndexDD = CUDD.Matrix.SetVectorElement(CUDD.Constant(0), varForThisChoice, choiceIndexForThisCommand, 1); CUDD.Ref(tmp); transDD = CUDD.Function.Plus(transDD, CUDD.Function.Times(tmp, choiceIndexDD)); } CUDD.Deref(tmp); } // take the i bits out of 'overlaps' overlaps = CUDD.Function.Times(overlaps, CUDD.Function.Not(guardHasIChoices)); } // store result compDDs.guards = covered; compDDs.trans = transDD; compDDs.min = currentAvailStartBit; compDDs.max = currentAvailStartBit + numDDChoiceVarsUsed; CUDD.Deref(overlaps); CUDD.Deref(guardDDs, commandDDs); return(compDDs); }
/// <summary> /// Get element in vector dd /// [ REFS: 'none', DEREFS: 'none' ] /// </summary> public static double GetVectorElement(CUDDNode dd, CUDDVars vars, int index) { return PlatformInvoke.DD_GetVectorElement(manager, dd.Ptr, vars.GetArrayPointer(), vars.GetNumVars(), index); }
/// <summary> /// Generates 0-1 ADD for the function x = y /// where x, y are num_vars-bit numbers encoded by variables x_vars, y_vars /// [ REFS: 'result', DEREFS: 'none' ] /// </summary> public static CUDDNode Identity(CUDDVars rVars, CUDDVars cVars) { return new CUDDNode(PlatformInvoke.DD_Identity(manager, rVars.GetArrayPointer(), cVars.GetArrayPointer(), rVars.GetNumVars())); }
public static CUDDNode ProbReachReward(CUDDNode trans, CUDDNode stateReward, CUDDNode transReward, CUDDNode reach, CUDDVars allRowVars, CUDDVars allColVars, CUDDNode maybe, CUDDNode inf) { CUDD.Ref(trans, maybe); CUDDNode a = CUDD.Function.Times(trans, maybe); CUDD.Ref(stateReward, maybe); CUDDNode newStateReward = CUDD.Function.Times(stateReward, maybe); CUDD.Ref(transReward, a); CUDDNode newTransRewards = CUDD.Function.Times(transReward, a); newTransRewards = CUDD.Abstract.SumAbstract(newTransRewards, allColVars); CUDDNode allReward = CUDD.Function.Plus(newStateReward, newTransRewards); // CUDDNode tmp = CUDD.Matrix.Identity(allRowVars, allColVars); CUDD.Ref(reach); tmp = CUDD.Function.And(tmp, reach); a = CUDD.Function.Minus(tmp, a); CUDDNode sol = Jacobi(a, allReward, allReward, reach, allRowVars, allColVars, 1); // set reward for infinity states to infinity CUDD.Ref(inf); sol = CUDD.Function.ITE(inf, CUDD.PlusInfinity(), sol); // CUDD.Deref(a, allReward); return sol; }
/// <summary> /// Returns matrix multiplication of matrices dd1 and dd2 /// [Calculates the product of two matrices represented as ADDs.] /// Description [Calculates the product of two matrices, A and B, /// represented as ADDs. This procedure implements the quasiring multiplication /// algorithm. A is assumed to depend on variables x (rows) and z /// (columns). B is assumed to depend on variables z (rows) and y /// (columns). The product of A and B then depends on x (rows) and y /// (columns). Only the z variables have to be explicitly identified; /// they are the "summation" variables. Returns a pointer to the /// result if successful; NULL otherwise.] /// [ REFS: 'result', DEREFS: 'dd1, dd2' ] /// </summary> /// <param name="dd1"></param> /// <param name="dd2"></param> /// <param name="vars">variable are shared by both dd1, dd2. Normally dd1 row + column, dd2 only column</param> /// <param name="method"></param> /// <returns></returns> public static CUDDNode MatrixMultiply(CUDDNode dd1, CUDDNode dd2, CUDDVars vars, int method) { return new CUDDNode(PlatformInvoke.DD_MatrixMultiply(manager, dd1.Ptr, dd2.Ptr, vars.GetArrayPointer(), vars.GetNumVars(), method)); }