/** * Return the sum of the integers in the list * * @param integerMap - The map of integers * @return - the sum of integers in the list */ private int sumOf(Map<Integer, Integer> integerList) { int sum = 0; // The sum for (Integer current : integerList.keySet()) { sum += integerList.get(current); } return sum; }
/** * Find out the maximum value for a given map of actions * * @param actions - The map of actions to their values * @return Return the action with the largest value out of all the actions */ private Action maxArg(Map<Action, Double> actions) { Action largestValue = null; // The largest value for (Action current : actions.keySet()) { if (largestValue == null || (actions.get(largestValue) < actions.get(current))) { largestValue = current; } } return largestValue; }
/** * Make a copy of a policy * * @param Map<State, Action> newPolicy - The new policy */ private void copyPolicy(Map<State, Action> newPolicy) { /* Containers for clones */ State current; Action currentAction; this.policy = new HashMap<State, Action>(); for (State newState : newPolicy.keySet()) { current = new State(newState.getState()); current.setCost(newState.getTemporaryCost()); currentAction = new Action(newPolicy.get(newState).getPurchases()); this.policy.put(current, currentAction); } }
/** * Transition function. Currently, we only get the list of probabilities of each item. * * @param current - The current state * @param action - The action * @param possible - The possible state * @return The list of probabilities where each index refers to the probability of that item */ private List<Double> transition(State current, Action action, State possible) { List<Double> probs = new ArrayList<Double>(); // Probabilities Map<Integer, Integer> currentStock, purchase, possibleStock; // Maps double currentProb; // The current probability Matrix currentMatrix; // The current probability matrix int row, column; // The row and column for (int i = 0; i < current.getState().size(); ++i) { currentProb = 0.0; currentStock = current.getState(); purchase = action.getPurchases(); possibleStock = possible.getState(); row = currentStock.get(i) + purchase.get(i); column = row - possible.getState().get(i); currentMatrix = this.probabilities.get(i); if (column < 0 || column >= currentMatrix.getNumCols() || row >= currentMatrix.getNumRows()) { // Invalid state probs.add(0.0); continue; } if (possibleStock.get(i) > 0 || (possibleStock.get(i) == 0 && column == 0)) { // Sufficiently provided currentProb = currentMatrix.get(row, column); } else if (possibleStock.get(i) == 0 && column > 0) { // Range of probabilities because user could have eaten plenty for (int j = column; j < currentMatrix.getNumCols(); ++j) { currentProb += currentMatrix.get(row, j); } } probs.add(currentProb); } return probs; }
/** Generate all possible actions */ private void generateAllPossibleActions() { double startTime, endTime; // Timer for generating states Map<Integer, Integer> action; // Action int maxSum = this.fridge.getMaxPurchase(); // The maximum amount we can purchase int maxIndex = this.fridge.getMaxTypes() - 1; // The maximum index of an action System.out.println("Generating all possible actions"); startTime = endTime = Global.currentTime(); /* Set the time */ action = new HashMap<Integer, Integer>(); /* Generate zero case */ for (int i = 0; i < (maxIndex + 1); ++i) { action.put(i, 0); } this.possibleActions.add(new Action(action)); System.out.println("Size of action: " + action.size()); while ((endTime - startTime) < this.MAX_GENERATION_TIME) { if (this.fridge.getMaxTypes() <= 0) { System.err.println("Invalid number of item types"); System.exit(10); } else if (this.fridge.getMaxTypes() == 1) { // Only have 1 type of item break; } else { // Fridge has 2 or more types of items for (int i = maxSum; i >= 0; --i) { for (int j = 0; j < (maxIndex + 1); ++j) { recursiveGeneration(1, maxSum, i, j, action, this.fridge.getMaxPurchase()); for (int k = 0; k < (maxIndex + 1); ++k) { // Reset list action.put(k, 0); } } endTime = Global.currentTime(); if ((endTime - startTime) >= this.MAX_GENERATION_TIME) { break; } } } endTime = Global.currentTime(); // Get current time this.timeRemaining -= (endTime - startTime); System.out.println("Time remaining: " + this.timeRemaining); break; } }
public List<Integer> generateShoppingList(List<Integer> inventory, int numWeeksLeft) { State current; // current state Map<Integer, Integer> purchases = new HashMap<Integer, Integer>(); // Purchases Map<Integer, Integer> map = new HashMap<Integer, Integer>(); // Mapping of integers List<Integer> shopping = new ArrayList<Integer>(); // Shopping items for (int i = 0; i < inventory.size(); ++i) { map.put(i, inventory.get(i)); } current = new State(map); purchases = this.policy.get(current).getPurchases(); for (int i = 0; i < inventory.size(); ++i) { shopping.add(purchases.get(i)); } return shopping; }
/** Generate all the possible states */ private void generateAllPossibleStates() { double startTime, endTime; // Timer for generating states Map<Integer, Integer> state; // Action int maxSum = this.fridge.getCapacity(); // The maximum amount we can have in a state int maxIndex = this.fridge.getMaxTypes() - 1; // The maximum index of a state System.out.println("Generating all possible states"); startTime = endTime = Global.currentTime(); /* Set the time */ state = new HashMap<Integer, Integer>(); /* Generate zero case */ for (int i = 0; i < (maxIndex + 1); ++i) { state.put(i, 0); } this.possibleStates.add(new State(state)); System.out.println("Size of state: " + state.size()); while ((endTime - startTime) < this.MAX_GENERATION_TIME) { if (this.fridge.getMaxTypes() <= 0) { System.exit(10); } else if (this.fridge.getMaxTypes() == 1) { // Only have 1 type of item break; } else { // Fridge has 2 or more types of items for (int i = maxSum; i >= 0; --i) { for (int j = 0; j < (maxIndex + 1); ++j) { recursiveGeneration(0, maxSum, i, j, state, this.fridge.getMaxItemsPerType()); for (int k = 0; k < (maxIndex + 1); ++k) { // Reset list state.put(k, 0); } } endTime = Global.currentTime(); if ((endTime - startTime) >= this.MAX_GENERATION_TIME) { break; } } } endTime = Global.currentTime(); // Get current time this.timeRemaining -= (endTime - startTime); System.out.println("Time remaining: " + this.timeRemaining); break; } }
/** * Recursively generate list based on given values * * @param int generateType - The type we are currently generating * @param int maxSum - The maximum sum * @param int remaining - The remaining value * @param int currentIndex - The current index we are looking at * @param Map<Integer, Integer> currentMap - Current map being modified * @param int maxVal - The maximum value */ private void recursiveGeneration( int generateType, int maxSum, int remaining, int currentIndex, Map<Integer, Integer> currentMap, int maxVal) { int localCurrentIndex = currentIndex; // The current index if (remaining < 0 || currentIndex > (this.fridge.getMaxTypes() - 1)) { addToList(generateType, currentMap); return; } else { for (int i = remaining; i >= 0; --i) { if (i >= maxVal) { // Too much remaining currentMap.put(currentIndex, maxVal); addToList(generateType, currentMap); recursiveGeneration( generateType, maxSum - maxVal, maxSum - maxVal, localCurrentIndex + 1, currentMap, maxVal); } else if (i == 0 && maxSum == 0) { // We are done clearFromCurrent(currentIndex, currentMap); addToList(generateType, currentMap); return; } else { // Just the right amount currentMap.put(currentIndex, i); addToList(generateType, currentMap); recursiveGeneration( generateType, maxSum - i, maxSum - i, localCurrentIndex + 1, currentMap, maxVal); } } } }
/** Generate optimal policy */ private void generateOptimalPolicy() { double startTime, currentTime; // Timer things boolean alreadyRunThrough = false; // Record if we've already done one run Set<State> toLookup; // The states to lookup Map<Action, Double> differentValues = new HashMap<Action, Double>(); // The different values for the current state Map<State, Action> newPolicy = new HashMap<State, Action>(); // New policy State newState; // New state for new policy Action best; // The best action startTime = Global.currentTime(); currentTime = Global.currentTime(); while ((currentTime - startTime) <= this.timeRemaining) { if (alreadyRunThrough) { toLookup = this.policy.keySet(); } else { toLookup = this.possibleStates; } for (State currentState : toLookup) { differentValues.clear(); // Reset different values for (Action currentAction : this.possibleActions) { if (!validAction(currentAction, currentState)) { continue; } differentValues.put( currentAction, valueGeneration(currentState, currentAction, toLookup)); } best = maxArg(differentValues); if (isBetterPolicy(currentState, differentValues.get(best))) { newState = new State(currentState.getState()); newState.setTemporaryCost(differentValues.get(best)); newPolicy.put(newState, best); } } if (CheckDifference(0.1, newPolicy)) { copyPolicy(newPolicy); newPolicy.clear(); alreadyRunThrough = true; } else { currentTime = Global.currentTime(); break; } } }
/** * Checks if the difference between the values of the previous policy and the new policy are <= * val. * * <p>Also reassigns the old policy * * @param double val - The difference * @param Map<State, Action> newPolicy - The new policy * @return true if the minimum difference > val. false otherwise */ private boolean CheckDifference(double val, Map<State, Action> newPolicy) { Double currDiff, minDiff = null; // The minimum and current difference if (this.policy.size() != this.possibleStates.size()) { // Previous policy wasn't assigned yet return true; } for (State current : newPolicy.keySet()) { for (State old : this.policy.keySet()) { if (current.equals(old)) { currDiff = Math.abs(current.getTemporaryCost() - old.getCost()); if (minDiff == null || currDiff <= minDiff) { minDiff = currDiff; } break; } } } if (minDiff > val) { return true; } return false; }
/** * Set to 0 everything from index current to size of map * * @param int current - The current index * @param Map<Integer, Integer> mapToClear - The map to clear */ private void clearFromCurrent(int current, Map<Integer, Integer> mapToClear) { for (int i = current; i < mapToClear.size(); ++i) { mapToClear.put(i, 0); } }