/** * Return a list of indices representing the next values that would be selected using the given * probabilities */ public IntegerVector getNextIndicesDeterministicallyUsingProbs(DoubleVector probs) { // Check the number of indices is equal to number of probabilities if (size() != probs.size()) { throw new ErrorException( "Number of probabilities (" + probs.size() + ") does not match the receiver (" + size() + ")"); } // Calculate the total number of samples for this selection (One more than the sum of the counts // so far) double n = 0; double cumProb = 0.0; for (int i = 0; i < size(); i++) { n += get(i); cumProb += probs.get(i); } double x = n + 1; if (Math.abs(cumProb - 1.0) > 0.001) { throw new ErrorException("Probabilities do not sum to 1.000"); } // Loop through indices IntegerVector sortedIndices = new IntegerVector(); DoubleVector sortedDiffs = new DoubleVector(); for (int i = 0; i < probs.size(); i++) { // Calculate the expected number of events for this probability double expectedNumber = x * probs.get(i); // Select the index with the largest difference between the current // number and the expected number of events double difference = expectedNumber - get(i); int destIndex = 0; for (int j = 0; j < sortedDiffs.size(); j++) { if (sortedDiffs.get(j) < difference) { break; } destIndex++; } sortedDiffs.add(destIndex, difference); sortedIndices.add(destIndex, i); } return sortedIndices; }
/** * Select indices deterministically from the given probability distribution. The float buffer * receiver of this method is the number of times that each index has been fully selected. The * given split determines how many distinct indices will be selected, and by how much they will be * incremented (the total increments add up to one). The same index can be selected twice. */ public IntegerVector selectIndicesDeterministicallyUsingProbs_SplitAllowDuplicateIndex( DoubleVector probs, DoubleVector split) { double n; double maxDifference; double cumProb; double expectedNumber; double difference; int selectedIndex; IntegerVector selectedIndices; // Check that the number of indices is equal to the number of probabilities if (!(this.size() == probs.size())) { throw new ErrorException("Number of probabilities does not match the number the receiver"); } // Check that there is a valid split if (split.size() == 0) { throw new ErrorException("No split given"); } /*else { if( Math.abs( (split.sum() - 1.0) ) > 0.001 ) { throw new ErrorException( "Split does not sum to 1.0" ); } }*/ selectedIndices = new IntegerVector(1, 1); // Calculate the total number of samples for this selection so far n = 0.0; cumProb = 0.0; for (int j = 1; j <= this.size(); j++) { n = (n + this.get(j - 1)); cumProb = (cumProb + probs.get(j - 1)); } if (Math.abs((cumProb - 1.0)) > 0.001) { throw new ErrorException("Probabilities do not sum to 1.000"); } for (int i = 1; i <= split.size(); i++) { n = (n + split.get(i - 1)); // Loop through the indices maxDifference = -100000.0; selectedIndex = 0; for (int j = 1; j <= probs.size(); j++) { if (probs.get(j - 1) > 0.0) { // Calculate the expected number of events for this // probability expectedNumber = (n * probs.get(j - 1)); // Select the index with the largest difference between // the current number and the expected number of events difference = (expectedNumber - this.get(j - 1)); if (!(maxDifference + 1.0E-10 >= difference)) { maxDifference = difference; selectedIndex = j; } } } if (selectedIndex == 0) { throw new ErrorException("Error in method"); } // Increment the count for this index this.addAt(split.get(i - 1), selectedIndex - 1); selectedIndices.add(selectedIndex); } return selectedIndices; }