package geniusweb.profile; import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; import java.util.HashSet; import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.Set; import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonGetter; import com.fasterxml.jackson.annotation.JsonProperty; import geniusweb.issuevalue.Bid; import geniusweb.issuevalue.Domain; /** * Default implementation of partial ordering that stores all is-better * relations explicitly in a map. * * NOTICE this can handle profiles of max size Integer. This is because various * functions used here rely on basic java functions that can handle only int. * Besides, the size of partial maps grows very rapidly so this approach is * limited anyway. */ public class DefaultPartialOrdering extends DefaultProfile implements PartialOrdering { /** * Set is sparsely filled. If a Bid is not a key, it is not better than any * other bid. */ private final Map> isBetter; /** * * @param name name of the profile * @param domain the {@link Domain} * @param reservationbid the reservation bid, this is the minimum acceptable * bid * @param bids a list of bids that this ordering contains * comparisons for * @param isbetterList a list of tuples [bid1index, bid2index]. It * indicates that bids[bid1index] isbetterthan * bids[bid2index]. */ @JsonCreator public DefaultPartialOrdering(@JsonProperty("name") String name, @JsonProperty("domain") Domain domain, @JsonProperty("reservationBid") Bid reservationbid, @JsonProperty("bids") List bids, @JsonProperty("better") List> isbetterList) { this(name, domain, reservationbid, makeBidMap(bids, isbetterList)); } /** * @param name the name for the profile * @param domain the {@link Domain} description * @param reservationbid the reservation {@link Bid} * @param isBetterMap a map with keys = a better bid and value=a less * good bid. */ public DefaultPartialOrdering(String name, Domain domain, Bid reservationbid, Map> isBetterMap) { super(name, domain, reservationbid); this.isBetter = isBetterMap; } @Override public boolean isPreferredOrEqual(Bid bid1, Bid bid2) { if (!isBetter.containsKey(bid1)) return false; return isBetter.get(bid1).contains(bid2); } /** * * @return a list with all the bids that are referred to, either as better * or as worse than another bid */ @JsonGetter public List getBids() { // FIXME the iteration order may not be guaranteed! Set bids = new HashSet<>(); for (Bid bid : isBetter.keySet()) { bids.add(bid); bids.addAll(isBetter.get(bid)); } return new ArrayList(bids); } @JsonGetter /** * * @return a list of tuples [bid1index, bid2index]. It indicates that * bids[bid1index] isbetterthan bids[bid2index]. */ public List> getBetter() { List> betterlist = new LinkedList<>(); List bidslist = getBids(); for (Bid bid : bidslist) { if (isBetter.containsKey(bid)) { for (Bid worsebid : isBetter.get(bid)) { betterlist.add(Arrays.asList(bidslist.indexOf(bid), bidslist.indexOf(worsebid))); } } } return betterlist; } @Override public String toString() { return "DefaultPartialOrdering[" + getValuesString() + "," + isBetter + "]"; } private static Map> makeBidMap(List bids, List> isBetterList) { Map> betterMap = new HashMap<>(); for (List tuple : isBetterList) { if (tuple.size() != 2) { throw new IllegalArgumentException("Expected tuple but found " + tuple + "in " + isBetterList); } Bid betterbid = bids.get(tuple.get(0)); Set map = betterMap.get(betterbid); if (map == null) { map = new HashSet<>(); betterMap.put(betterbid, map); } map.add(bids.get(tuple.get(1))); } return betterMap; } @Override public int hashCode() { final int prime = 31; int result = super.hashCode(); result = prime * result + ((isBetter == null) ? 0 : isBetter.hashCode()); return result; } @Override public boolean equals(Object obj) { if (this == obj) return true; if (!super.equals(obj)) return false; if (getClass() != obj.getClass()) return false; DefaultPartialOrdering other = (DefaultPartialOrdering) obj; if (isBetter == null) { if (other.isBetter != null) return false; } else if (!isBetter.equals(other.isBetter)) return false; return true; } }