[1] | 1 | package agents.anac.y2016.farma.etc;
|
---|
| 2 |
|
---|
| 3 | import java.util.ArrayList;
|
---|
| 4 | import java.util.HashMap;
|
---|
| 5 |
|
---|
| 6 | import genius.core.Bid;
|
---|
| 7 | import genius.core.utility.AbstractUtilitySpace;
|
---|
| 8 |
|
---|
| 9 | public class negotiationStrategy {
|
---|
| 10 | private AbstractUtilitySpace utilitySpace;
|
---|
| 11 | private negotiationInfo negotiationInfo;
|
---|
| 12 | private double df = 0.0; // 割引係数
|
---|
| 13 | private double rv = 0.0; // 留保価格
|
---|
| 14 |
|
---|
| 15 | private boolean isPrinting = false; // デバッグ用
|
---|
| 16 |
|
---|
| 17 | public negotiationStrategy(AbstractUtilitySpace utilitySpace,
|
---|
| 18 | negotiationInfo negotiationInfo, boolean isPrinting) {
|
---|
| 19 | this.utilitySpace = utilitySpace;
|
---|
| 20 | this.negotiationInfo = negotiationInfo;
|
---|
| 21 | this.isPrinting = isPrinting;
|
---|
| 22 | df = utilitySpace.getDiscountFactor();
|
---|
| 23 | rv = utilitySpace.getReservationValue();
|
---|
| 24 | }
|
---|
| 25 |
|
---|
| 26 | // 受容判定
|
---|
| 27 | public boolean selectAccept(Bid offeredBid, double time) {
|
---|
| 28 | try {
|
---|
| 29 | if (utilitySpace.getUtility(offeredBid) >= getThreshold(time)) {
|
---|
| 30 | return true;
|
---|
| 31 | } else {
|
---|
| 32 | return false;
|
---|
| 33 | }
|
---|
| 34 | } catch (Exception e) {
|
---|
| 35 | System.out.println("受容判定に失敗しました");
|
---|
| 36 | e.printStackTrace();
|
---|
| 37 | return false;
|
---|
| 38 | }
|
---|
| 39 | }
|
---|
| 40 |
|
---|
| 41 | // 交渉終了判定
|
---|
| 42 | public boolean selectEndNegotiation(double time) {
|
---|
| 43 | // 時刻timeの割引効用を考慮した留保価格が閾値を上回った時EndNegotiation
|
---|
| 44 | if (utilitySpace.getReservationValueWithDiscount(time) >= getThreshold(time))
|
---|
| 45 | return true;
|
---|
| 46 |
|
---|
| 47 | double weightedDF = df * 2.0;
|
---|
| 48 | if (time > 0.5 && rv > weightedDF) {
|
---|
| 49 | ArrayList<Object> opponents = negotiationInfo.getOpponents();
|
---|
| 50 | double minDIST = 1.0;
|
---|
| 51 | double maxEmax = 0.0;
|
---|
| 52 | for (Object sender : opponents) {
|
---|
| 53 | minDIST = Math.min(minDIST,
|
---|
| 54 | negotiationInfo.calSpaceDistByInitOffer(sender));
|
---|
| 55 | maxEmax = Math.max(maxEmax, calEmax(sender));
|
---|
| 56 | }
|
---|
| 57 | if (maxEmax < minDIST)
|
---|
| 58 | return true;
|
---|
| 59 | }
|
---|
| 60 | return false;
|
---|
| 61 | }
|
---|
| 62 |
|
---|
| 63 | public boolean isWorthNegotiation() {
|
---|
| 64 | boolean isWorth = true;
|
---|
| 65 | // HashMap
|
---|
| 66 |
|
---|
| 67 | return isWorth;
|
---|
| 68 | }
|
---|
| 69 |
|
---|
| 70 | // 閾値を返す
|
---|
| 71 | public double getThreshold(double time) {
|
---|
| 72 | double lowerLimitThreshold = calLowerLimitThreshold(time);
|
---|
| 73 | double threshold = 1.0;
|
---|
| 74 |
|
---|
| 75 | // 割引効用が存在するかどうか
|
---|
| 76 | if (utilitySpace.isDiscounted()) {
|
---|
| 77 | /*
|
---|
| 78 | * 割引効用が存在する場合、早期の合意形成が要求される したがって、閾値を早めに下げておく必要性がある
|
---|
| 79 | */
|
---|
| 80 | threshold = 0.95; // 序盤から閾値を少し下げておくことでOfferの柔軟性を少し上げる
|
---|
| 81 | double temp = 1.0 - (1 - df) * Math.log1p(time * (Math.E - 1));
|
---|
| 82 | // double temp = 1.0 - (1-df) * Math.pow(Math.E, time - df);
|
---|
| 83 | threshold = Math.min(threshold, temp);
|
---|
| 84 |
|
---|
| 85 | } else {
|
---|
| 86 | /*
|
---|
| 87 | * 割引効用が存在しない場合、早くに交渉を成立させる意味がなくなるため、より長く交渉を続けることが要求される
|
---|
| 88 | * つまり、bidデータを多く活用できるため統計的なアプローチでも一定の意味を持つという判断のもと以下のような閾値をとることとする
|
---|
| 89 | */
|
---|
| 90 | threshold = statisticalThreshold(time, threshold);
|
---|
| 91 |
|
---|
| 92 | }
|
---|
| 93 | // 閾値の下限との比較
|
---|
| 94 | threshold = Math.max(threshold, lowerLimitThreshold);
|
---|
| 95 |
|
---|
| 96 | return threshold;
|
---|
| 97 |
|
---|
| 98 | }
|
---|
| 99 |
|
---|
| 100 | public double calEmax(Object sender) {
|
---|
| 101 | double m = negotiationInfo.getAverage(sender);
|
---|
| 102 | double sd = negotiationInfo.getStandardDeviation(sender);
|
---|
| 103 | return m + (1 - m) * calWidth(m, sd);
|
---|
| 104 | }
|
---|
| 105 |
|
---|
| 106 | public double statisticalThreshold(double time, double threshold) {
|
---|
| 107 | double originalAlpha = 3.5 + rv; // 最初は線形的に閾値を下げていく
|
---|
| 108 | HashMap<Object, Double> emaxs = new HashMap<Object, Double>();
|
---|
| 109 | HashMap<Object, Double> targets = new HashMap<Object, Double>();
|
---|
| 110 |
|
---|
| 111 | ArrayList<Object> opponents = negotiationInfo.getOpponents();
|
---|
| 112 | for (Object sender : opponents) {
|
---|
| 113 | // alphaが大きいほど強硬、小さいほど譲歩に柔軟な姿勢を示す
|
---|
| 114 | double alpha = Math
|
---|
| 115 | .max(0.1,
|
---|
| 116 | originalAlpha
|
---|
| 117 | - calAlpha(negotiationInfo
|
---|
| 118 | .calAssertiveness(sender),
|
---|
| 119 | negotiationInfo
|
---|
| 120 | .calCooperativeness(sender)));
|
---|
| 121 |
|
---|
| 122 | // double m = negotiationInfo.getAverage(sender);
|
---|
| 123 | // double v = negotiationInfo.getVariancer(sender);
|
---|
| 124 | // double sd = negotiationInfo.getStandardDeviation(sender);
|
---|
| 125 |
|
---|
| 126 | emaxs.put(sender, calEmax(sender));
|
---|
| 127 | double target = 1 - (1 - emaxs.get(sender)) * Math.pow(time, alpha);
|
---|
| 128 | targets.put(sender, target);
|
---|
| 129 |
|
---|
| 130 | threshold = Math.min(threshold, target);
|
---|
| 131 | }
|
---|
| 132 | return threshold;
|
---|
| 133 | }
|
---|
| 134 |
|
---|
| 135 | /**
|
---|
| 136 | * 統計情報を元に相手の変位幅を推定
|
---|
| 137 | *
|
---|
| 138 | * @param m
|
---|
| 139 | * @param sd
|
---|
| 140 | * @return
|
---|
| 141 | */
|
---|
| 142 | public double calWidth(double m, double sd) {
|
---|
| 143 | if (m > 0.0 && m < 1.0) {
|
---|
| 144 | return Math.sqrt(3.0 / (m - m * m)) * sd;
|
---|
| 145 | } else {
|
---|
| 146 | return Math.sqrt(12) * sd;
|
---|
| 147 | }
|
---|
| 148 | }
|
---|
| 149 |
|
---|
| 150 | /**
|
---|
| 151 | * 割引効用がない場合の譲歩の強硬・柔軟性を調整する
|
---|
| 152 | *
|
---|
| 153 | * @param assertiveValue
|
---|
| 154 | * @param cooperativeValue
|
---|
| 155 | * @return
|
---|
| 156 | */
|
---|
| 157 | public double calAlpha(double assertiveValue, double cooperativeValue) {
|
---|
| 158 | double ans = cooperativeValue - assertiveValue;
|
---|
| 159 | return ans;
|
---|
| 160 | }
|
---|
| 161 |
|
---|
| 162 | /**
|
---|
| 163 | * 現在の割引効用下の留保価格以上の効用値を得ることができる効用値を閾値の下限とする
|
---|
| 164 | *
|
---|
| 165 | * @param time
|
---|
| 166 | * @return
|
---|
| 167 | */
|
---|
| 168 | public double calLowerLimitThreshold(double time) {
|
---|
| 169 | double lowerLimitThreshold = rv;
|
---|
| 170 | if (utilitySpace.isDiscounted()) {
|
---|
| 171 | lowerLimitThreshold = 0.30 + rv * 0.2;
|
---|
| 172 | } else {
|
---|
| 173 | lowerLimitThreshold = 0.55 + rv * 0.2;
|
---|
| 174 | }
|
---|
| 175 |
|
---|
| 176 | ArrayList<Object> opponents = negotiationInfo.getOpponents();
|
---|
| 177 | double minEmax = 1.0;
|
---|
| 178 | for (Object sender : opponents) {
|
---|
| 179 | minEmax = Math.min(minEmax, calEmax(sender));
|
---|
| 180 | }
|
---|
| 181 |
|
---|
| 182 | lowerLimitThreshold = Math.max(lowerLimitThreshold, minEmax);
|
---|
| 183 | if (rv == 0.0 && time > 0.99) {
|
---|
| 184 | lowerLimitThreshold *= 0.85;
|
---|
| 185 | }
|
---|
| 186 | System.out.println("LowerThreshold4: " + lowerLimitThreshold);
|
---|
| 187 | return lowerLimitThreshold;
|
---|
| 188 | }
|
---|
| 189 |
|
---|
| 190 | }
|
---|