/* * avenir: Predictive analytic based on Hadoop Map Reduce * Author: Pranab Ghosh * * Licensed under the Apache License, Version 2.0 (the "License"); you * may not use this file except in compliance with the License. You may * obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or * implied. See the License for the specific language governing * permissions and limitations under the License. */ package org.avenir.reinforce; import java.util.ArrayList; import java.util.List; import java.util.ListIterator; import org.chombo.util.DynamicBean; /** * Manages a group of items with reward data * @author pranab * */ public class GroupedItems { private List<DynamicBean> groupItems = new ArrayList<DynamicBean>(); public static final String ITEM_ID = "itemID"; public static final String ITEM_COUNT = "count"; public static final String ITEM_REWARD = "reward"; public static final String ITEM_USE_COUNT = "useCount"; private static final int ZERO_COUNT = 0; private static final int ONE_COUNT = 1; /** * */ public void initialize() { groupItems.clear(); } /** * @param itemID * @param count * @param reward */ public void createtem(String itemID, int count, int reward) { DynamicBean item = new DynamicBean(); item.set(ITEM_ID, itemID); item.set(ITEM_COUNT, count); item.set(ITEM_REWARD, reward); item.set(ITEM_USE_COUNT, ZERO_COUNT); groupItems.add(item); } /** * @return */ public List<DynamicBean> getGroupItems() { return groupItems; } /** * @param groupItems */ public void setGroupItems(List<DynamicBean> groupItems) { this.groupItems = groupItems; } /** * @param item */ public void add(DynamicBean item) { groupItems.add(item); } /** * @param item */ public void remove(DynamicBean item) { groupItems.remove(item); } public int size() { return groupItems.size(); } /** * @param items * @param batchSize * @return */ public List<DynamicBean> collectItemsNotTried(int batchSize) { //collect items not tried before int thisCount = 0; int thisUseCount = 0; List<DynamicBean> collectedItems = new ArrayList<DynamicBean>(); ListIterator<DynamicBean> iter = groupItems.listIterator(); while (iter.hasNext()) { DynamicBean groupItem = iter.next(); thisCount = groupItem.getInt(ITEM_COUNT); thisUseCount = groupItem.getInt(ITEM_USE_COUNT); if (thisCount == ZERO_COUNT && thisUseCount == ZERO_COUNT) { if (collectedItems.size() < batchSize) { collectedItems.add(groupItem); } else if (collectedItems.size() == batchSize) { break; } } } return collectedItems; } /** * select item randomly * @return */ public DynamicBean selectRandom() { int select = (int)Math.round( Math.random() * groupItems.size()); select = select < groupItems.size() ? select : groupItems.size() -1; DynamicBean item = groupItems.get(select); setUseCount(item); return item; } /** * select item with maximum reward * @return */ public DynamicBean getMaxRewardItem() { int reward = 0; int maxReward = 0; DynamicBean maxRewardItem = null; //max reward in this group for (DynamicBean groupItem : groupItems) { reward = groupItem.getInt(ITEM_REWARD); if (reward > maxReward) { maxReward = reward; maxRewardItem = groupItem; } } return maxRewardItem; } /** * select item with maximum reward * @return */ public DynamicBean selectMaxRewardItem() { DynamicBean maxRewardItem = getMaxRewardItem(); if (null != maxRewardItem) { setUseCount(maxRewardItem); } return maxRewardItem; } /** * @param selectedItem */ public DynamicBean select(DynamicBean selectedItem) { incrUseCount(selectedItem); return selectedItem; } /** * @param selectedItem * @param reward * @return */ public DynamicBean select(DynamicBean selectedItem, int reward) { updateReward(selectedItem, reward); incrUseCount(selectedItem); return selectedItem; } /** * @return */ public boolean anyItemTried() { boolean anyTried = false; for (DynamicBean groupItem : groupItems) { if (groupItem.getInt(ITEM_COUNT) > 0) { anyTried = true; break; } } return anyTried; } /** * @param groupItem * @return */ public int getUsageCount(DynamicBean groupItem) { return groupItem.getInt(ITEM_USE_COUNT); } /** * @param groupItem */ public int getTrialCount(DynamicBean groupItem) { return groupItem.getInt(ITEM_COUNT); } /** * @param groupItem */ public int getReward(DynamicBean groupItem) { return groupItem.getInt(ITEM_REWARD); } /** * @param groupItem */ public void setReward(DynamicBean groupItem, int reward) { groupItem.set(ITEM_REWARD, reward); } /** * @param groupItem */ public void setUseCount(DynamicBean groupItem) { groupItem.set(ITEM_USE_COUNT, ONE_COUNT); } /** * @param groupItem */ public void incrUseCount(DynamicBean groupItem) { groupItem.set(ITEM_USE_COUNT, groupItem.getInt(ITEM_USE_COUNT) + ONE_COUNT); } /** * @param groupItem */ public void clearUseCount(DynamicBean groupItem) { groupItem.set(ITEM_USE_COUNT, ZERO_COUNT); } /** * */ public void clearAllUseCount() { for (DynamicBean groupItem : groupItems) { groupItem.set(ITEM_USE_COUNT, ZERO_COUNT); } } /** * @param groupItem * @return */ public int getTotalCount(DynamicBean groupItem) { return groupItem.getInt(ITEM_COUNT) + groupItem.getInt(ITEM_USE_COUNT); } /** * @param groupItem * @return */ public boolean isAlreadySelected(DynamicBean groupItem) { return groupItem.getInt(ITEM_USE_COUNT) > ZERO_COUNT; } /** * @param groupItem * @return */ public void updateReward(DynamicBean groupItem, int reward) { int count = getTotalCount(groupItem); int newReward = (getReward(groupItem) * count + reward) / (count + 1); setReward(groupItem, newReward); } }