Closed SeSodesa closed 2 years ago
I am not sure what you are after with the rank. For the votes per person rule you can simply project it out. Then, your encoding is equivalent to the following:
#const n = 4.
#const m = 4.
person(1..n).
candidate(1..m).
% Person P chooses a (single) rank R ∈ 1..3 to a unique candidate C.
rank(P,C) :- person(P), candidate(C).
% Count the number of votes each person gave
votesperp(P,V) :- person(P), V = #count { C: candidate(C), rank(P,C) }.
Maybe you want to use <= 1
as a guard for the aggregate when guessing the rank?
I am not sure what you are after with the rank.
The idea is that we have a ranked-choice voting system, and the voter gives their preference per election candidate, with number 1 being the most preferrable and rank 3 signifying the least preferrable candidate. Therefore I need a numerical value stored in there somewhere.
I then reverse those later with
points(P, 3, C) :- rank(P, 1, C).
points(P, 2, C) :- rank(P, 2, C).
points(P, 1, C) :- rank(P, 3, C).
and calculate a score as the sum of the points per candidate:
score(C, S)
:-
candidate(C),
S = #sum {
Poi, P:
person(P),
points(P, Poi, C)
}
.
The person with the highest score is then elected, if there is no draw:
% If there is a draw, the candidates involved cannot get elected.
draw(C1, C2)
:-
candidate(C1),
candidate(C2),
C1 != C2,
score(C1, S1),
score(C2, S2),
S1 = S2
.
% The candidate with the highest score gets elected.
elected(C)
:-
candidate(C),
score(C, S),
S = #max {
Sco, Can:
score(Can, Sco)
},
not draw(C, C2) : candidate(C2)
.
However, this does not seem to produce the exact results I want, possibly
because a single person P
is able to vote for more than 3 candidates C
.
Is the following what you intend?
rank(1..3).
{ rank(P,R,C) } :- person(P), rank(R), candidate(C).
% a person can give at most three votes
:- { rank(P,R,C) } > 3, person(P).
% a person can give at most one rank to a candidate
:- { rank(P,R,C) } > 1, person(P), candidate(C).
% a person can use each rank at most once
:- { rank(P,R,C) } > 1, person(P), rank(R).
This could also be written differently by first guessing a vote and then assigning a rank to the vote.
Since I am trying to figure out aggregates, are those basically equivalent to
% a person can give at most three votes
:- 3 < #count { rank(P,R,C) }, person(P), candidate(C), rank(R).
% a person can give at most one rank to a candidate
:- 1 < #count { C : rank(P,R,C) }, person(P), candidate(C).
% a person can use each rank at most once
:- 1 < #count { R : rank(P,R,C) }, person(P), rank(R), candidate(C).
?
It has to be
:- 3 < #count { R,C: rank(P,R,C) }, person(P).
% or equivalently
:- 3 < #count { R,C: rank(P,R,C), rank(R), candidate(C) }, person(P).
% a person can give at most one rank to a candidate
:- 1 < #count { R : rank(P,R,C) }, person(P), candidate(C).
% or equivalently
:- 1 < #count { R : rank(P,R,C), rank(R) }, person(P), candidate(C).
% a person can use each rank at most once
:- 1 < #count { C : rank(P,R,C) }, person(P), rank(R).
% or equivalently
:- 1 < #count { C : rank(P,R,C), candidate(C) }, person(P), rank(R).
I also like to write the bound on the right-hand-side because I find term relation constant
easier to read. Except for assignments where I prefer variable equal term
.
Ah, alright. Reading the Potassco user manual somehow had me think that the lower bound always has to be on the left side, because of all the examples with
lower bound ⪯ α { tᵢ : 𝐋ᵢ } ⪯ upper bound
but it is somewhat of a relief if that is note the case.
Historically, aggregates hat the form L { E } U
without any relation symbols. The last revision of the guide is a bit dated and was still written with this mindset. Now, one can (and should) use relation symbols.
Hi, just a remark from the off: This may have been a valuable discussion for our mailing list. @SeSodesa, in case you are interested feel free to subscribe here
Hello.
I am in the process of trying to understand Clingo's aggregates via the following exercise:
I have implemented the first predicate as follows:
Now all is fine and good, as long as I don't comment out the line
votesperp(P, V)
:Each person votes for all candidates exactly once, fulfilling the uniqueness condition. However, when I try to use the
votesperp/2
construct to restrict the number of candidates each person votes for like thisthen the following happens:
Why cannot I restrict the number of votes to 3 per person like this? Thanks for any assistance.