package agents; import genius.core.Bid; import genius.core.BidIterator; import genius.core.analysis.BidPoint; import genius.core.analysis.ParetoFrontier; import genius.core.utility.AdditiveUtilitySpace; import genius.core.utility.UtilitySpace; /** * Like {@link ParetoFrontier}, but with extra functionality. This version loads * the frontier by itself using the given utility spaces. * *

notes

We may decide to move these functions into * {@link ParetoFrontier}. * * When a utility space changes, you currently just need to make a new * {@link ParetoFrontierPlus} from scratch using the constructor. This is * because we can not listen to changes in {@link AdditiveUtilitySpace}s * * @author W.Pasman 3sep14 * */ public class ParetoFrontierPlus { UtilitySpace mySpace, otherSpace; private ParetoFrontier pareto = null; /** * Get a {@link ParetoFrontier} for this outcome space. * * @throws Exception */ public ParetoFrontierPlus(UtilitySpace spaceMe, UtilitySpace spaceOther) { mySpace = spaceMe; otherSpace = spaceOther; try { computeParetoFrontier(); } catch (Exception e) { throw new IllegalStateException( "Failed to compute Pareto Frontier", e); } } /** * compute the pareto frontier. Warning, this may take some time and may * even run out of memory if the space is really large. * * @throws Exception * if getUtility fails. * */ private void computeParetoFrontier() throws Exception { Bid bid; BidIterator bids = new BidIterator(mySpace.getDomain()); pareto = new ParetoFrontier(); while (bids.hasNext()) { bid = bids.next(); BidPoint bp = new BidPoint(bid, mySpace.getUtility(bid), otherSpace.getUtility(bid)); pareto.mergeIntoFrontier(bp); } pareto.sort(); } /** * Project a utility onto a pareto frontier point * * @param otherUtil * the utility that the projected point should be close to. * @return a {@link BidPoint} on the pareto that has minimal distance to the * given otherUtil. */ public BidPoint getBidNearOpponentUtility(double otherUtil) { BidPoint nearest = null; double dist = 10; // larger than any real distance in utilspace. for (BidPoint bidpoint : pareto.getFrontier()) { double newdist = Math.abs(bidpoint.getUtilityB() - otherUtil); if (newdist < dist) { nearest = bidpoint; dist = newdist; } } return nearest; } /** * get the bid on the pareto that has myUtility nearest to given target * utility * * @param bid * @return */ public BidPoint getBidNearMyUtility(double utility) { BidPoint nearest = null; double dist = 10; // larger than any real distance in utilspace. for (BidPoint bidpoint : pareto.getFrontier()) { double newdist = Math.abs(bidpoint.getUtilityA() - utility); if (newdist < dist) { nearest = bidpoint; dist = newdist; } } return nearest; } /** * get the bid on the pareto that has at least the given utility for me (as * close as possible to the target) * * @param utility * target utility for me. * @return bid that is nearest bid above or at target utility for me. May * return null if no such bid. */ public BidPoint getBidWithMinimumUtility(double utility) { BidPoint nearest = null; double dist = 10; // larger than any real distance in utilspace. double newdist; for (BidPoint bidpoint : pareto.getFrontier()) { newdist = bidpoint.getUtilityA() - utility; if (newdist > 0 && newdist < dist) { nearest = bidpoint; dist = newdist; } } return nearest; } }