1 | package geniusweb.voting.votingevaluators;
|
---|
2 |
|
---|
3 | import java.util.Collections;
|
---|
4 | import java.util.Comparator;
|
---|
5 | import java.util.HashSet;
|
---|
6 | import java.util.Map;
|
---|
7 | import java.util.Set;
|
---|
8 |
|
---|
9 | import com.fasterxml.jackson.annotation.JsonCreator;
|
---|
10 | import com.fasterxml.jackson.annotation.JsonIgnore;
|
---|
11 |
|
---|
12 | import geniusweb.actions.PartyId;
|
---|
13 | import geniusweb.inform.Agreements;
|
---|
14 | import geniusweb.issuevalue.Bid;
|
---|
15 | import geniusweb.voting.CollectedVotes;
|
---|
16 | import geniusweb.voting.VotingEvaluator;
|
---|
17 |
|
---|
18 | /**
|
---|
19 | * {@link #getAgreements()} collects all possible {@link Agreements}. We're
|
---|
20 | * finished only when {@link #getAgreements()} covers all except possibly 1
|
---|
21 | * party.
|
---|
22 | *
|
---|
23 | * The agreements is a list of {@link Bid}s and a maximum-sized list of
|
---|
24 | * {@link PartyId}s that placed a satisfied vote for that bid. maximum-sized
|
---|
25 | * means that there is no larger subset of votes for that bid. There may be
|
---|
26 | * other subsets of equal size for the bid. If there are no agreements at all
|
---|
27 | * for a bid, the bid is not placed in the map.
|
---|
28 | *
|
---|
29 | */
|
---|
30 | public class LargestAgreementsLoop implements VotingEvaluator {
|
---|
31 | @JsonIgnore
|
---|
32 | private final CollectedVotes allVotes;
|
---|
33 |
|
---|
34 | // caching
|
---|
35 | @JsonIgnore
|
---|
36 | private Agreements maxAgreements = null;
|
---|
37 |
|
---|
38 | @JsonCreator
|
---|
39 | public LargestAgreementsLoop() {
|
---|
40 | this(new CollectedVotes(Collections.emptyMap(),
|
---|
41 | Collections.emptyMap()));
|
---|
42 | }
|
---|
43 |
|
---|
44 | protected LargestAgreementsLoop(CollectedVotes votes) {
|
---|
45 | this.allVotes = votes;
|
---|
46 | }
|
---|
47 |
|
---|
48 | @Override
|
---|
49 | public Agreements getAgreements() {
|
---|
50 | if (maxAgreements == null)
|
---|
51 | maxAgreements = collectAgreements();
|
---|
52 | return maxAgreements;
|
---|
53 | }
|
---|
54 |
|
---|
55 | @Override
|
---|
56 | public boolean isFinished() {
|
---|
57 | HashSet<PartyId> parties = new HashSet<PartyId>(
|
---|
58 | allVotes.getVotes().keySet());
|
---|
59 | parties.removeAll(getAgreements().getMap().keySet());
|
---|
60 | return parties.size() < 2;
|
---|
61 | }
|
---|
62 |
|
---|
63 | @Override
|
---|
64 | public VotingEvaluator create(CollectedVotes votes) {
|
---|
65 | return new LargestAgreementsLoop(votes);
|
---|
66 | }
|
---|
67 |
|
---|
68 | /**
|
---|
69 | * @return the agreements that were reached from the given votes, using the
|
---|
70 | * greedy algorithm picking the largets votesets.
|
---|
71 | */
|
---|
72 | protected Agreements collectAgreements() {
|
---|
73 | CollectedVotes remainingvotes = allVotes;
|
---|
74 | Agreements newagreements = new Agreements();
|
---|
75 | while (true) {
|
---|
76 | Map<Bid, Set<PartyId>> agrees = remainingvotes.getMaxAgreements();
|
---|
77 | if (agrees.isEmpty())
|
---|
78 | break;
|
---|
79 | // find the bid with max group power
|
---|
80 | Bid maxbid = agrees.keySet().stream()
|
---|
81 | .max(Comparator.comparingInt(
|
---|
82 | bid -> allVotes.getTotalPower(agrees.get(bid))))
|
---|
83 | .get();
|
---|
84 | Set<PartyId> maxparties = agrees.get(maxbid);
|
---|
85 | newagreements = newagreements
|
---|
86 | .with(new Agreements(maxbid, maxparties));
|
---|
87 | remainingvotes = remainingvotes.without(maxparties);
|
---|
88 | }
|
---|
89 | return newagreements;
|
---|
90 | }
|
---|
91 |
|
---|
92 | /**
|
---|
93 | * WARNING you must manually set prime=37 here to fix collision with
|
---|
94 | * {@link LargestAgreement}.
|
---|
95 | */
|
---|
96 | @Override
|
---|
97 | public int hashCode() {
|
---|
98 | final int prime = 37;
|
---|
99 | int result = 1;
|
---|
100 | result = prime * result
|
---|
101 | + ((allVotes == null) ? 0 : allVotes.hashCode());
|
---|
102 | return result;
|
---|
103 | }
|
---|
104 |
|
---|
105 | @Override
|
---|
106 | public boolean equals(Object obj) {
|
---|
107 | if (this == obj)
|
---|
108 | return true;
|
---|
109 | if (obj == null)
|
---|
110 | return false;
|
---|
111 | if (getClass() != obj.getClass())
|
---|
112 | return false;
|
---|
113 | LargestAgreementsLoop other = (LargestAgreementsLoop) obj;
|
---|
114 | if (allVotes == null) {
|
---|
115 | if (other.allVotes != null)
|
---|
116 | return false;
|
---|
117 | } else if (!allVotes.equals(other.allVotes))
|
---|
118 | return false;
|
---|
119 | return true;
|
---|
120 | }
|
---|
121 |
|
---|
122 | @Override
|
---|
123 | public String toString() {
|
---|
124 | return "LargestAgreementsLoop";
|
---|
125 | }
|
---|
126 | }
|
---|