/// <summary> /// THe most challenging function. This calculates the probability for changing to each state, and the time left before changing. /// It takes into account the fact that some states have been half in on state and half in another during it's wait. /// </summary> /// <param name="bayesNode">The node we are calculating the probability for.</param> /// <returns></returns> private BayesNode calculateNextProb(BayesNode bayesNode) { if (!isCurrentlyChangeable(bayesNode)) return bayesNode; if(bayesNode.VariableName == "lightning") Console.Write("f"); //I dunno... something default. Assuming default prob is 1.0/n double[] probsSum = new double[bayesNode.States.Count]; for(uint i=0; i!=probsSum.Length; ++i) if(i!=bayesNode.ObservedValue) probsSum[i] = 1/(probsSum.Length-1); probsSum[bayesNode.ObservedValue] = 1.0; int count = 1; double[] avgProb = new double[bayesNode.States.Count]; foreach (BayesEdge be in getNodesInfluences(bayesNode.VariableName).Values) { //The duration is stored as the negative sum, at the x,x index for state x. string influencersState; if (be.CIMs.ContainsKey(influencersState = be.NodeA.States[(int)be.NodeA.ObservedValue])) { for (int i = 0; i != probsSum.Length; ++i) probsSum[i] += be.CIMs[influencersState][bayesNode.ObservedValue][i]; ++count; } } for (int i = 0; i != probsSum.Length; ++i) avgProb[i] = probsSum[i]/count; double time = avgProb[bayesNode.ObservedValue]; //this if statement is merely for initialization from what I remember. if (bayesNode.timeLeft == 0) { bayesNode.timeLeft = time; bayesNode.nextVarProbs = avgProb; } else { //this assumes timeLeft is being updated somewhere else. //This is the amount of time left ratio. So the new state only affects the var as much as it should. double modifier = bayesNode.timeLeft / (bayesNode.nextVarProbs[bayesNode.ObservedValue]); //Apply modifier to probs for(int i=0; i!=avgProb.Length; ++i) avgProb[i] *= modifier; //get new probs. Generally they shouldn't change much. Ie. if only 2 variables effect the node, //then it may change a lot, but if 10 variables effect the node it will change very little (1/10). for (int i = 0; i != avgProb.Length; ++i) bayesNode.nextVarProbs[i] = (bayesNode.nextVarProbs[i] + avgProb[i]) / 2; bayesNode.nextVarProbs[bayesNode.ObservedValue] = (bayesNode.timeLeft = bayesNode.nextVarProbs.Sum() - bayesNode.nextVarProbs[bayesNode.ObservedValue]); } return bayesNode; }
private BayesNode linearlyInfer(BayesNode bayesNode) { Random r = new Random(); //Normalized dice roll. // -1, because we disclude the current state. We are CHANGING states. double diceRoll = r.NextDouble() * (bayesNode.nextVarProbs.Sum() - 1); double currentSum = 0.0; for (uint i = 0; i != bayesNode.nextVarProbs.Length; ++i) { if(i != bayesNode.ObservedValue) //discluding the time element. if (diceRoll <= (currentSum += bayesNode.nextVarProbs[i])) { bayesNode.ObservedValue = i; //set the new state. break; } } return bayesNode; }
/// <summary> /// checks to see if the node can change under the current circumstances. /// </summary> /// <param name="n">the node in question.</param> /// <returns></returns> public bool isCurrentlyChangeable(BayesNode n) { foreach (BayesEdge be in getNodesInfluences(n.VariableName).Values) if (be.CIMs.ContainsKey(be.NodeA.States[(int)be.NodeA.ObservedValue])) return true; return false; }