📄 multinomialpotential.java
字号:
public DiscretePotential marginalizeOut (Variable var) { Set newVars = varSet (); newVars.remove (var); return marginalizeInternal (new MultinomialPotential (newVars)); } private DiscretePotential marginalizeInternal (MultinomialPotential result) { result.setAll (0.0); if (inLogSpace) result.logify (); int[] projection = largeIdxToSmall (result); /* Add each element of the single array of the large potential to the correct element in the small potential. */ for (int largeIdx = 0; largeIdx < probs.singleSize (); largeIdx++) { /* Convert a single-index from this distribution to one for the smaller distribution */ int smallIdx = projection[largeIdx]; /* Whew! Now, add it in. */ double oldValue = this.probs.singleValue (largeIdx); if (inLogSpace) { double currentValue = result.probs.singleValue (smallIdx); result.probs.setSingleValue (smallIdx, Maths.sumLogProb (oldValue, currentValue)); } else { result.probs.incrementSingleValue (smallIdx, oldValue); } } return result; } public DiscretePotential extractMax (Variable var) { return extractMaxInternal (new MultinomialPotential (var)); } public DiscretePotential extractMax (Variable[] vars) { return extractMaxInternal (new MultinomialPotential (vars)); } public DiscretePotential extractMax (Collection vars) { return extractMaxInternal (new MultinomialPotential (vars)); } private DiscretePotential extractMaxInternal (MultinomialPotential result) { result.setAll (Double.NEGATIVE_INFINITY); result.inLogSpace = inLogSpace; int[] projection = largeIdxToSmall (result); /* Add each element of the single array of the large potential to the correct element in the small potential. */ for (int largeIdx = 0; largeIdx < probs.singleSize (); largeIdx++) { /* Convert a single-index from this distribution to one for the smaller distribution */ int smallIdx = projection[largeIdx]; /* Whew! Now, add it in. */ double largeValue = this.probs.singleValue (largeIdx); double smallValue = result.probs.singleValue (smallIdx); if (largeValue > smallValue) { result.probs.setSingleValue (smallIdx, largeValue); } } return result; } private void expandToContain (MultinomialPotential pot) { // Check if we're adding variables Set newVarSet = new HashSet (pot.varSet ()); newVarSet.addAll (varSet ()); // if so, expand this potential. this is not pretty if (newVarSet.size () > numVars) { MultinomialPotential newPtl = new MultinomialPotential (newVarSet); newPtl.multiplyByInternal (this); varMap = newPtl.varMap; probs = newPtl.probs; numVars = newPtl.numVars; clearProjectionCache (); } } /** * Does the conceptual equivalent of this *= pot. * Assumes that pot's variables are a subset of * this potential's. */ public void multiplyBy (DiscretePotential pot) { MultinomialPotential pot1 = (MultinomialPotential) pot; // cheating expandToContain (pot1); pot1 = ensureSameLogity (pot1); if (inLogSpace) { plusEqualsInternal (pot1); } else { multiplyByInternal (pot1); } } /** * Ensures that <tt>this.inLogSpace == ptl.inLogSpace</tt>. If this is * not the case, return a copy of ptl logified or delogified as appropriate. * * @param ptl * @return A potential equivalent to ptl, possibly logified or delogified. * ptl itself could be returned. */ private MultinomialPotential ensureSameLogity (MultinomialPotential ptl) { if (inLogSpace && !ptl.inLogSpace) { return (MultinomialPotential) ptl.log (); } else if (!inLogSpace && ptl.inLogSpace) { return (MultinomialPotential) ptl.delog (); } else { // inLogSpace == ptl.inLogSpace return ptl; } } // Does destructive multiplication on this, assuming this has all // the variables in pot. private void multiplyByInternal (MultinomialPotential ptl) { int[] projection = largeIdxToSmall (ptl); for (int singleIdx = 0; singleIdx < probs.singleSize (); singleIdx++) { int smallIdx = projection[singleIdx]; double prev = this.probs.singleValue (singleIdx); double newVal = ptl.probs.singleValue (smallIdx); this.probs.setSingleValue (singleIdx, prev * newVal); } } /** * Returns the elementwise product of this potential and * another one. */ public DiscretePotential multiply (DiscretePotential dist) { DiscretePotential result = duplicate (); result.multiplyBy (dist); return result; } public static MultinomialPotential multiplyAll (DiscretePotential[] phis) { return multiplyAll (Arrays.asList (phis)); } /** * Returns the product of a collection of multinomial potentials. */ /// xxx once there are other types of potentials, this will need to /// be refactored into a Potentials static-utilities class. public static MultinomialPotential multiplyAll (Collection phis) { /* Get all the variables */ HashSet varSet = new HashSet (); for (Iterator it = phis.iterator (); it.hasNext ();) { MultinomialPotential phi = (MultinomialPotential) it.next (); varSet.addAll (phi.varSet ()); } /* define a new potential over the neighbors of NODE */ MultinomialPotential newCPF = new MultinomialPotential (varSet); for (Iterator it = phis.iterator (); it.hasNext ();) { DiscretePotential phi = (DiscretePotential) it.next (); newCPF.multiplyBy (phi); } return newCPF; } /** * Does the conceptual equivalent of this /= pot. * Assumes that pot's variables are a subset of * this potential's. */ public void divideBy (DiscretePotential pot) { MultinomialPotential pot1 = (MultinomialPotential) pot; // cheating expandToContain (pot1); pot1 = ensureSameLogity (pot1); if (inLogSpace) { minusEqualsInternal (pot1); } else { divideByInternal (pot1); } } // Does destructive divison on this, assuming this has all // the variables in pot. private void divideByInternal (MultinomialPotential ptl) { MultinomialPotential ptl1 = (MultinomialPotential) ptl; // cheating int[] projection = largeIdxToSmall (ptl1); for (int singleIdx = 0; singleIdx < probs.singleSize (); singleIdx++) { int smallIdx = projection[singleIdx]; double prev = this.probs.singleValue (singleIdx); double newVal = ptl1.probs.singleValue (smallIdx); double product = prev / newVal; /* by convention, let dividing by zero just return 0 */ if (Double.isNaN (product)) { product = 0; } this.probs.setSingleValue (singleIdx, product); } } /** * Does the conceptual equivalent of this -= pot. * Assumes that pot's variables are a subset of * this potential's. */ private void minusEqualsInternal (MultinomialPotential ptl) { int[] projection = largeIdxToSmall (ptl); for (int singleIdx = 0; singleIdx < probs.singleSize (); singleIdx++) { int smallIdx = projection[singleIdx]; double prev = this.probs.singleValue (singleIdx); double newVal = ptl.probs.singleValue (smallIdx); double product = prev - newVal; /* by convention, let -Inf + Inf (corresponds to 0/0) be -Inf */ if (Double.isNaN (product)) product = Double.NEGATIVE_INFINITY; this.probs.setSingleValue (singleIdx, product); } } /** * Does the conceptual equivalent of this += pot. * Assumes that pot's variables are a subset of * this potential's. */ private void plusEqualsInternal (MultinomialPotential ptl) { int[] projection = largeIdxToSmall (ptl); for (int singleIdx = 0; singleIdx < probs.singleSize (); singleIdx++) { int smallIdx = projection[singleIdx]; double prev = this.probs.singleValue (singleIdx); double newVal = ptl.probs.singleValue (smallIdx); double product = prev + newVal; this.probs.setSingleValue (singleIdx, product); } } // xxx Should return an assignment public int argmax () { int bestIdx = 0; double bestVal = probs.singleValue (0); for (int idx = 1; idx < probs.singleSize (); idx++) { double val = probs.singleValue (idx); if (val > bestVal) { bestVal = val; bestIdx = idx; } } return bestIdx; } public boolean almostEquals (DiscretePotential p) { return almostEquals (p, Maths.EPSILON); } public boolean almostEquals (DiscretePotential p, double epsilon) { if (!(p instanceof MultinomialPotential)) { return false; } MultinomialPotential p2 = (MultinomialPotential) p; if (!varSet ().containsAll (p2.varSet ())) { return false; }/* TODO: fold into probs.almostEqauals() if variable ordering * issues ever resolved. Also, consider using this in all * those hasConverged() functions. */ int[] projection = largeIdxToSmall (p2); for (int idx1 = 0; idx1 < probs.singleSize (); idx1++) { int idx2 = projection[idx1]; double v1 = probs.singleValue (idx1); double v2 = p2.probs.singleValue (idx2); if (Math.abs (v1 - v2) > epsilon) { return false; } } return true; } public DiscretePotential duplicate () { MultinomialPotential dup = new MultinomialPotential (varMap, probs); dup.inLogSpace = inLogSpace; return dup; } public Object clone () { return duplicate (); } public String toString () { StringBuffer s = new StringBuffer (1024); s.append ("Potential "); if (inLogSpace) { s.append ("[LOG] "); } s.append ("\n Variables: \n"); for (int i = 0; i < numVars; i++) { s.append (varMap.lookupObject (i).toString ()); s.append (" "); } s.append ("\n"); for (int i = 0; i < numVars; i++) { s.append (i); s.append (" "); } s.append ("\n\n"); int indices[] = new int[numVars]; s.append (probs.singleSize ()); s.append ("\n"); double sum = 0.0; for (int i = 0; i < probs.singleSize (); i++) { probs.singleToIndices (i, indices); for (int j = 0; j < numVars; j++) { s.append (indices[j]); s.append (" "); } double val = probs.singleValue (i); sum += val; s.append (val); s.append ("\n"); } s.append (" Sum = " + sum + "\n"); return s.toString (); }; // Indicates whether this potential is the log of some other potential. private boolean inLogSpace = false; public boolean isInLogSpace () { return inLogSpace; } public void logify () { if (!inLogSpace) { inLogSpace = true; for (int i = 0; i < probs.singleSize (); i++) { probs.setSingleValue (i, Math.log (probs.singleValue (i))); } } } public void delogify () { if (inLogSpace) { inLogSpace = false; for (int i = 0; i < probs.singleSize (); i++) { probs.setSingleValue (i, Math.exp (probs.singleValue (i))); } } } public DiscretePotential log () { DiscretePotential dup = duplicate (); dup.logify (); return dup; } public DiscretePotential delog () { DiscretePotential dup = duplicate (); dup.delogify (); return dup; } public boolean isNaN () { return probs.isNaN (); } public void printValues () { System.out.print ("["); for (int i = 0; i < probs.singleSize (); i++) { System.out.print (probs.singleValue (i)); System.out.print (", "); } System.out.print ("]"); } public void printSizes () { int[] sizes = new int[numVars]; probs.getDimensions (sizes); System.out.print ("["); for (int i = 0; i < numVars; i++) { System.out.print (sizes[i] + ", "); } System.out.print ("]"); } public double logphi (Assignment assn) { if (inLogSpace) { return phi (assn); } else { return Math.log (phi (assn)); } }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -