package bargainingchips.utilityfunctions; import bargainingchips.Bundle; import bargainingchips.BundleBuilder; import bargainingchips.Chip; import bargainingchips.ChipIssueValue; import bargainingchips.ChipIssueValueBuilder; import bargainingchips.wishlist.WishList; import bargainingchips.wishlist.WishListBuilder; /** * * In addition to {@link wishList}, this utility function inputs piecewise linear curves as for desired * quantity and price per each {@link Chip}. * To this end, the buyer designates 2 `Double' data points, namely p1 and p2, for the price of each {@link Chip}, * where the utility of offers lower than or equal to p1 and higher than or equal to p2 will be * respectively 1 and 0. That is, it is flattened and peaked for values before p1. For the prices offered * between p1 and p2, it has a downward slope. * Quantity is similar to price but also mirrors for quantities less than the exact quantity per each * {@link Chip} at {@link wishList}, that is flattened and peaked at 1 around the exact quantity. To this end, * it inputs 4 `Integer' data deviation, namely d1, d2, d3, and d4, for the acceptable quantities of each {@link Chip} * around the exact wished quantity q, where the utility of quantities lower than or equal to q-d1 or higher * than or equal to q+d4 will be 0, the utility of quantities higher than or equal to q-d2 or less than or equal to q+d3 * will be 1, for the quantities offered between q+d3 and q+d4, it has a downward slope, and for the quantities offered * between q+d1 and q+d2, it has an upward slope. * * * * @author Faria Nassiri-Mofakham * */ public class UF_PeakedFlatPricePeakedFlatQuantity implements UtilityFunction { private WishList wishlist; // the exact wished quantity per each Chip // Other parts of the buyer's preferences are assigned with desirability degrees of a variety of prices and quantities per each Chip. private ChipIssueValue qtyDeviation; // `Indivisible' or `divisible' space; list of 4 data points of type `Double' for discreet or continues values; The deviation around the wished quantity per each {@link Chip} could be asymmetric. private ChipIssueValue uQty; // list of respected single utility for data points regarding quantity deviations private ChipIssueValue breakEvenPrice; // list of 2 data points of type Double determining the price curve private ChipIssueValue uBreakEvenPrice; // list of respected single utility for data points regarding price deviations private ChipIssueValue lambdaC; // importance of each Chip (i.e, color) private double lambdaP,lambdaQ; // importance of issues (i.e., price, quantity, etc) public UF_PeakedFlatPricePeakedFlatQuantity(WishList w, ChipIssueValue qty, ChipIssueValue uQy, ChipIssueValue bEP, ChipIssueValue uBEP, ChipIssueValue lc, double lp, double lq) { wishlist=w; qtyDeviation=qty; uQty=uQy; breakEvenPrice=bEP; uBreakEvenPrice=uBEP; lambdaC=lc; lambdaP=lp; lambdaQ=lq; } @Override public Double getUtility(Bundle b) { double sumWeightedPrice=0.0; double sumWeightedQty=0.0; if (b!=null) { for (Chip c : wishlist) { int desiredQ = wishlist.getQuantity(c); Double[] qtyDev = qtyDeviation.getUnitValue(c); // gives 4 data deviation for quantity if (qtyDev.length > 4) throw new IllegalStateException("\n\n[Warning] UF_PeakedFlatPriceAndPeakedFlatQuantity::getUtility(Bundle). Input only 4 quantity data deviation! "+ qtyDev); Double[] uQy = uQty.getUnitValue(c); // gives asymmetric utility for the data points in jumping from flat (sloped) to sloped(flat) lines if (uQy.length > 4) throw new IllegalStateException("\n\n[Warning] UF_PeakedFlatPriceAndPeakedFlatQuantity::getUtility(Bundle). Input only 4 values for utility of quantity data points in jumping from flat (sloped) to sloped(flat) lines! "+ uQy); Double[] desiredP = (Double[]) breakEvenPrice.getUnitValue(c); // gives 4 data points for price if (desiredP.length > 4) throw new IllegalStateException("\n\n[Warning] UF_PeakedFlatPriceAndPeakedFlatQuantity::getUtility(Bundle). Input only 4 price data points! "+ desiredP); Double[] uPrices= uBreakEvenPrice.getUnitValue(c); // gives utility for the first and second data points in jumping from flat to sloped line if (uPrices.length > 2) throw new IllegalStateException("\n\n[Warning] UF_PeakedFlatPriceAndPeakedFlatQuantity::getUtility(Bundle). Input only 2 values for utility of price data points in jumping from flat to sloped line! "+ uPrices); Double importanceC= lambdaC.getUnitValue(c); Integer offeredQ = b.getQuantity(c); if (offeredQ == null) offeredQ = 0; Double offeredP= b.getUnitPrice(c); sumWeightedPrice += importanceC * uPrice(offeredP, desiredP,uPrices); sumWeightedQty += importanceC * uQuantity(offeredQ, desiredQ, qtyDev, uQy); } double u = lambdaP * sumWeightedPrice + lambdaQ * sumWeightedQty; return ( (u>1) ? 1 : ( (u<0) ? 0 : u) ); } return 0.0; } /** * @param param: the offered price * @param data: the designated price data points * @param uData: the utility of the the price data points * @return the utility regarding the offered price */ private double uPrice(double param, Double[] data, Double[] uData) { return ((param <= data[0]) ? 1 : (param >= data[1]) ? 0 : uSlope(param, data[0], data[1], uData[0], uData[1]) ); } /** * @param param: the offered quantity * @param data: the designated quantity data points * @param uData: the utility of quantity data points * @return the utility regarding the offered quantity */ private double uQuantity(double param, double q, Double[] data, Double[] uData) { return ( (param <= q-data[0] || param >= q+data[3]) ? 0 : ( (param > q-data[0] && param <= q-data[1] ) ? uSlope(param, data[0], data[1], uData[0], uData[1]) : ( (param > q+data[2] && param < q+data[3]) ? uSlope(param, data[2], data[3], uData[2], uData[3]) : 1) ) ); } private double uSlope(double param, double data1, double data2, Double uData1, Double uData2) { return (param-data1)*(uData1-uData2)/(data1-data2)+uData1; } /** * @return a String list of values assigned to a single variable, e.g. list of quantities or prices of a {@link Chip} **/ private String writeT(ChipIssueValue t) { String s = "{"; Double[] j; if (t!=null) { for (Chip c: t) { s += " " + c.toString() + "={"; j= t.getUnitValue(c); //System.out.println("j: "+j); for (int k=0; k deviations = new ChipIssueValueBuilder().addIssue("Green", new Double[] {100.0, 20.0, 50.0, 500.0}).addIssue("Yellow", new Double[] {50.0, 30.0, 30.0, 50.0}).addIssue("Orange", new Double[] {200.0, 40.0, 60.0, 1000.0}).build(); ChipIssueValue uDev = new ChipIssueValueBuilder().addIssue("Green", new Double[] {0.25, 0.8, 0.9, 0.1}).addIssue("Yellow", new Double[] {0.3, 0.7, 0.7, 0.3}).addIssue("Orange", new Double[] {0.15, 0.95, 0.85, 0.3}).build(); ChipIssueValue prices = new ChipIssueValueBuilder().addIssue("Green", new Double[] {3.0, 3.5, 4.8, 5.0}).addIssue("Yellow", new Double[] {5.0, 5.2, 6.2, 8.0}).addIssue("Orange", new Double[] {1.0, 1.8, 2.5, 3.0}).build(); ChipIssueValue uPrices = new ChipIssueValueBuilder().addIssue("Green", new Double[] {0.7, 0.2}).addIssue("Yellow", new Double[] {0.8, 0.1}).addIssue("Orange", new Double[] {0.9, 0.3}).build(); ChipIssueValue wC = new ChipIssueValueBuilder().addIssue("Green", 0.5).addIssue("Yellow", 0.3).addIssue("Orange", 0.2).build(); double wP = 0.6; double wQ = 0.4; UF_PeakedFlatPricePeakedFlatQuantity u = new UF_PeakedFlatPricePeakedFlatQuantity (wishlist, deviations, uDev, prices, uPrices, wC, wP, wQ); System.out.println(u); Bundle offer = new BundleBuilder() .addStack("Green", 2.0, 3) .addStack("Yellow", 5.0, 4) .addStack("Orange", 1.0, 17) //--- // .addStack("Green", 3.0, 4) //should give utility 1.0 in weighted additive // .addStack("Yellow", 5.0, 6) // .addStack("Orange", 1.0, 40) //--- // .addStack("Green", 10.0, 1) //should give utility 0.0 in weighted additive // .addStack("Yellow", 10.0, 1) // .addStack("Orange", 10.0, 1) //--- // .addStack("Red", 1.0, 6) // .addStack("Green", 3.0, 15) // .addStack("Purple", 0.10, 10) .build(); System.out.println(u.getUtility(offer)); } }