package com.plectix.simulator.simulationclasses.probability;
import static org.junit.Assert.fail;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import com.plectix.simulator.simulationclasses.probability.WeightedItemWithId.WeightFunction;
public class TestSelector {
int numberOfWeightedItems;
int numberOfUpdates;
int numberOfSelection;
private static final double CONFIDENCE_BOUND = 0.07;
List<WeightedItemWithId> weightedItemList;
WeightedItemSelector<WeightedItemWithId> weightedItemSelector;
// true -> using Random() false Random()
private boolean permitRandom = false;
public void setUp(WeightedItemSelector<WeightedItemWithId> testedSelector,
int testedNumberOfWeightedItems, int testedNumberOfUpdates,
int testedNumberOfSelection, WeightFunction typeOfWeight)
throws Exception {
weightedItemList = new ArrayList<WeightedItemWithId>();
weightedItemSelector = testedSelector;
numberOfWeightedItems = testedNumberOfWeightedItems;
numberOfUpdates = testedNumberOfUpdates;
numberOfSelection = testedNumberOfSelection;
for (int i = 0; i < numberOfWeightedItems; i++) {
weightedItemList.add(new WeightedItemWithId(i,
numberOfWeightedItems, typeOfWeight));
}
shuffleAndUpdate();
}
public void setWeightedItemList(List<WeightedItemWithId> list) {
weightedItemList = list;
}
public boolean testRandom() {
shuffleAndUpdate();
processSelection();
return equiprobability();
}
public boolean testRemoveAssigneSineAndRandom(int frequencyRemoved) {
assignSineAndParabolaWeight();
removeSomeItems(frequencyRemoved);
resetCounts();
shuffleAndUpdate();
processSelection();
return equiprobability();
}
public boolean testRemoveRecalculationAndRandom(int frequencyRemoved) {
assignOtherWeight();
removeSomeItems(frequencyRemoved);
resetCounts();
shuffleAndUpdate();
processSelection();
return equiprobability();
}
public void process() {
shuffleAndUpdate();
processSelection();
}
private void removeSomeItems(int k) {
for (int i = 0; i < numberOfWeightedItems; i++) {
WeightedItemWithId item = weightedItemList.get(i);
if (item.getId() % k != 0) {
item.remove();
}
}
}
private void resetCounts() {
for (int i = 0; i < numberOfWeightedItems; i++) {
weightedItemList.get(i).resetCount();
}
}
private void assignSineAndParabolaWeight() {
for (int i = 0; i < numberOfWeightedItems; i++) {
WeightedItemWithId item = weightedItemList.get(i);
if (item.getId() % 2 == 0)
item.setWeightFunction(WeightFunction.SINE);
if (item.getId() % 7 == 1)
item.setWeightFunction(WeightFunction.PARABOLA);
}
}
private void assignOtherWeight() {
for (int i = 0; i < numberOfWeightedItems; i++) {
WeightedItemWithId item = weightedItemList.get(i);
if (item.getId() % 5 == 0)
item.setWeightFunction(WeightFunction.LOGARITHM);
if (item.getId() % 7 == 1)
item.setWeightFunction(WeightFunction.PARABOLA);
}
}
private void shuffleAndUpdate() {
if (permitRandom) {
for (int i = 0; i < numberOfUpdates; i++) {
Collections.shuffle(weightedItemList);
weightedItemSelector.updatedItems(weightedItemList);
}
} else {
weightedItemSelector.updatedItems(weightedItemList);
}
}
private void processSelection() {
for (int i = 0; i < numberOfSelection; i++) {
WeightedItemWithId item = weightedItemSelector.select();
item.incrementCount();
}
}
private boolean equiprobability() {
int errors = 0;
double sumOfWeights = 0;
for (int i = 0; i < numberOfWeightedItems; i++) {
sumOfWeights += weightedItemList.get(i).getWeight();
}
for (int i = 0; i < numberOfWeightedItems; i++) {
if (weightedItemList.get(i).getWeight() != 0) {
if (!confidenceTest(weightedItemList.get(i).getCount(),
weightedItemList.get(i).getWeight() / sumOfWeights)) {
errors++;
}
} else {
if (weightedItemList.get(i).getCount() > 0)
fail("Item with 0 weight was selected!!!!!");
}
}
return errors < CONFIDENCE_BOUND * numberOfWeightedItems;
}
// 1.92 - from tables for 95% confidence interval
private boolean confidenceTest(int experimentalNumberOfEvents,
double expectedProbability) {
return Math.abs((experimentalNumberOfEvents - expectedProbability
* numberOfSelection)
/ Math.sqrt(numberOfSelection * expectedProbability
* (1 - expectedProbability))) < 1.92;
}
public boolean boundaryTest() {
for (int i = 0; i < numberOfWeightedItems; i++) {
WeightedItemWithId wi = new WeightedItemWithId(i,
numberOfWeightedItems, WeightFunction.ZERO);
weightedItemList.add(wi);
}
for (int i = numberOfWeightedItems; i < 2 * numberOfWeightedItems; i++) {
WeightedItemWithId wi = new WeightedItemWithId(i,
numberOfWeightedItems, WeightFunction.BIG);
weightedItemList.add(wi);
}
setWeightedItemList(weightedItemList);
process();
for (WeightedItemWithId wi : weightedItemList) {
if (wi.getWeight() == 0 && wi.getCount() > 0) {
return false;
}
}
weightedItemList.clear();
for (int i = 0; i < numberOfWeightedItems; i++) {
WeightedItemWithId wi = new WeightedItemWithId(i,
numberOfWeightedItems, WeightFunction.ONE);
weightedItemList.add(wi);
}
for (int i = numberOfWeightedItems; i < numberOfWeightedItems + 10; i++) {
WeightedItemWithId wi = new WeightedItemWithId(i,
numberOfWeightedItems, WeightFunction.BIG);
weightedItemList.add(wi);
}
process();
boolean flag = false;
for (WeightedItemWithId wi : weightedItemList) {
if (wi.getWeight() == 1 && wi.getCount() > 0) {
flag = true;
break;
}
}
if (!flag) {
System.err
.println("very rarely event is occured in testProbability");
}
return true;
}
}