Clarify definition of ties between candidates

-- (c) 2010-2011, Dermot Cochran, IT University of Copenhagen
-- http://www.kindsoftware.com/about/people/dc
-- http://www.itu.dk/people/dero

module Voting

open util/integer

-- An individual person standing for election
sig Candidate {
    votes: 			  set Ballot, 	-- First preference ballots assigned to this candidate
	transfers: 	      set Ballot,   -- Ballots received by transfer from another candidate
	surplus: 		  set Ballot, 	-- Ballots given to another candidate (on election or elimination)
	outcome: 		  Event
} {
	no b: Ballot | b in votes & transfers
	all b: Ballot | b in votes + transfers implies this in b.assignees
	surplus in votes + transfers
	Election.method = Plurality implies #surplus = 0 and #transfers = 0
}

-- A digital or paper artifact which accurately records the intentions of the voter
sig Ballot {
  assignees: 		set Candidate,  -- Candidates to which this ballot has been assigned
  preferences: 	seq Candidate  -- Ranking of candidates
} {
	assignees in preferences.elems
    not preferences.hasDups
	preferences.elems in Election.candidates
	preferences.first in assignees
	Election.method = Plurality implies #preferences = 1
    0 < #preferences
}

-- An election result
one sig Scenario {
   	losers: 				set Candidate,
   	winners: 			set Candidate,
	eliminated: 		set Candidate, 		-- Early and Sore Losers under STV rules
	threshold: 		Int, 						-- Minimum number of votes for a Loser or Early Loser
	quota: 				Int						-- Minimum number of votes for a STV Winner or Quota Winner
}
{
 	winners + losers = Election.candidates
 	#winners = Election.seats
 	no c: Candidate | c in losers & winners
 	0 < #losers
 	all w: Candidate | all l: Candidate | l in losers and w in winners implies
		((#l.votes + #l.transfers <= #w.votes + #w.transfers) and (#l.votes <= #w.votes))
    threshold = 1 + quota.div[4]
	Election.method = Plurality implies #eliminated = 0
	eliminated in losers
	all c: Candidate | c in losers implies Election.method = Plurality
       or #c.votes + #c.transfers < quota
}

/*
	There are four winner-outcomes and six loser-outcomes:

	Winner: 						(W1) elected in the first round of counting either by quota or plurality,
	QuotaWinner: 				(W2) elected with transfers from another candidate (STV only),
	CompromiseWinner: 	(W3) elected on the last round of counting without quota (STV only),
	TiedWinner:					(W4) elected by tie breaker,
	TiedLoser:					(L1) loses only by tie breaker but reaches the threshold,
	Loser:			 				(L2) defeated on last round but reaches the minimum threshold of votes,
    TiedEarlyLoser:			(L3) reaches threshold but eliminated by tie breaker (STV only),
	EarlyLoser:					(L4) reaches threshold but is eliminated before last round (STV only),
	TiedSoreLoser:				(L5) loses only by tie breaker but does not reach threshold,
	SoreLoser: 					(L6) does not even reach the mimimum threshold of votes.
*/
enum Event {Winner, QuotaWinner, CompromiseWinner, TiedWinner,
	TiedLoser, Loser, TiedEarlyLoser, EarlyLoser, TiedSoreLoser, SoreLoser}

enum Method {Plurality, STV}

-- An Election Constituency
one sig Election {
  candidates: 	set Candidate,
  seats: 				Int,
  method: 			Method,
  ballots:			Int -- number of ballots cast
}
{
 	0 < seats
 	seats < #candidates
 	all c: Candidate | c in candidates
    ballots = #Ballot
    Scenario.quota = 1 + ballots.div[seats+1]
}

-- Independent (or Fundamental) Axioms

fact surplus {
  all c: Candidate | (c.outcome = Winner and Election.method = STV) implies
     Scenario.quota + #c.surplus = #c.votes
}

fact winnersWithoutTransfers {
  all c: Candidate | (c.outcome = Winner and Election.method = STV) implies #c.transfers = 0
}

fact surplusFromTransfers {
  all c: Candidate | c.outcome = QuotaWinner implies ((surplus in transfers) and
     ((Scenario.quota + #c.surplus) = (#c.votes + #c.transfers)))
}

fact integrity {
  all c: Candidate | all b: Ballot | b in c.votes implies c in b.assignees
}

fact pluralityEvents {
	all c: Candidate | Election.method = Plurality implies
		(c.outcome = Loser or c.outcome = SoreLoser or c.outcome = Winner or
		c.outcome = TiedWinner or c.outcome = TiedLoser)
}

fact winnerSTV {
	all c: Candidate | (Election.method = STV and c.outcome = Winner) implies
       Scenario.quota <= #c.votes
}

fact transferWinnerWithQuota {
	all c: Candidate | (Election.method = STV and c.outcome = QuotaWinner) implies
	   Scenario.quota <= #c.votes + #c.transfers
}

fact transferWinnerNotFirst {
	all c: Candidate |  (Election.method = STV and c.outcome = QuotaWinner) implies
		not Scenario.quota <= #c.votes
}

fact closeWinner {
	all c: Candidate | (c.outcome = CompromiseWinner or c.outcome = TiedWinner) implies
		not (Scenario.quota <= #c.votes + #c.transfers) or Election.method = Plurality
}

fact soreLoser {
	all c: Candidate | (c.outcome = SoreLoser or c.outcome = TiedSoreLoser) implies
		((#c.votes + #c.transfers) < Scenario.threshold)
}

fact loser {
	all c: Candidate | (c.outcome = Loser or c.outcome = TiedLoser)
        implies (c in Scenario.losers and c not in Scenario.eliminated)
}

fact earlyLoser {
	all c: Candidate | (c.outcome = EarlyLoser or c.outcome = TiedEarlyLoser) iff
		(c in Scenario.eliminated and not (#c.votes + #c.transfers < Scenario.threshold))
}

fact winners {
	all c: Candidate | c in Scenario.winners iff
		(c.outcome = Winner or c.outcome = QuotaWinner or c.outcome = CompromiseWinner or
		c.outcome = TiedWinner)
}

fact losers {
	all c: Candidate | c in Scenario.losers iff
		(c.outcome = Loser or c.outcome = EarlyLoser or c.outcome = SoreLoser or
		c.outcome = TiedLoser or c.outcome = TiedEarlyLoser or c.outcome = TiedSoreLoser)
}

-- Non-Independent Axioms for Ballot Integrity
fact transfers {
	all c: Candidate | 0 < #c.transfers implies Election.method = STV
}

fact onlyWinnersAndQuotaWinnersHaveSurplus {
	all c: Candidate | 0 < #c.surplus implies
		(c.outcome = Winner or c.outcome = QuotaWinner)
}

fact winnersNeedNoTransfers {
		all c: Candidate | c.outcome = Winner implies 0 = #c.transfers
}

fact firstPreference {
	all b: Ballot | all c: Candidate | b.preferences.first = c iff b in c.votes
}

fact sizeOfSurplus {
	all c: Candidate | (c in Scenario.winners and Election.method = STV and 0 < #c.surplus) implies
		(#c.surplus = #c.votes + #c.transfers - Scenario.quota)
}

fact transferToNextPreference {
	all b: Ballot | all disj donor,receiver: Candidate |
		(donor + receiver in b.assignees and
		b in receiver.transfers and b in donor.surplus) implies
		(b.preferences.idxOf[donor] < b.preferences.idxOf[receiver] and
		receiver in b.preferences.rest.elems)
}

fact pluralityWinner {
	all disj a, b: Candidate | (Election.method = Plurality and Election.seats = 1 and
		a.outcome = Winner) implies #b.votes <= #a.votes
}

fact transferToNextContinuingCandidate {
	all disj skipped, receiving: Candidate | all b: Ballot |
		b.preferences.idxOf[skipped] < b.preferences.idxOf[receiving] and
		receiving in b.assignees and (not skipped in b.assignees) implies
		(skipped in Scenario.eliminated or skipped.outcome = Winner or
		skipped.outcome = QuotaWinner)
}

// All ballot transfers are associated with the last candidate to receive the transfer
fact ownership {
	all disj c,d: Candidate | all b: Ballot | b in c.transfers implies c in b.assignees and
		(d not in b.assignees or b.preferences.idxOf[d] < b.preferences.idxOf[c])
}

// Lowest candidate is eliminated first
fact lowestElimination {
	all disj c,d: Candidate | c in Scenario.eliminated and d not in Scenario.eliminated implies
		#c.votes + #c.transfers <= #d.votes + #d.transfers
}

// All ties involve equality between at least one winner and at least one loser on either original votes or
// on transfers plus original votes
fact equalityOfTiedWinner {
   all w: Candidate | some l: Candidate | w.outcome = TiedWinner and
	 	(l.outcome = TiedLoser or l.outcome = TiedSoreLoser or l.outcome = TiedEarlyLoser) implies
		(#l.votes = #w.votes) or (#l.votes + #l.transfers = #w.votes + #w.transfers)
}

fact equalityOfTiedLosers {
  all s: Candidate | some w: Candidate | w.outcome = TiedWinner and
       (s.outcome = SoreLoser or s.outcome = TiedLoser or s.outcome = TiedEarlyLoser) implies
       (#s.votes = #w.votes) or (#s.votes + #s.transfers = #w.votes + #w.transfers)
}

-- Scenario Validity Axioms
// When there is a tied sore loser then there are no non-sore losers
fact typeOfTiedLoser {
   no disj a,b: Candidate | a.outcome = TiedSoreLoser and
        (b.outcome = TiedLoser or b.outcome = TiedEarlyLoser or
         b.outcome=Loser or b.outcome=EarlyLoser)
}

fact tieBreaker {
	all w: Candidate | some l: Candidate | w.outcome = TiedWinner implies
		(l.outcome = TiedLoser or l.outcome = TiedSoreLoser or l.outcome = TiedEarlyLoser)
}

fact validTieBreaker {
	all l: Candidate | some w: Candidate |
    (l.outcome = TiedLoser or l.outcome = TiedSoreLoser or l.outcome = TiedEarlyLoser) implies
    w.outcome = TiedWinner and (#w.votes + #w.transfers = #l.votes + #l.transfers)
}

// Compromise winner must have more votes than any tied winners
fact compromiseNotTied {
	all disj c,t: Candidate | (c.outcome = CompromiseWinner and t.outcome = TiedWinner) implies
		#t.votes + #t.transfers < #c.votes + #c.transfers
}

// Equal losers are tied
fact equalityofTiedWinnersAndLosers {
	all disj w,l: Candidate | w in Scenario.winners and l in Scenario.losers and
		#w.votes = #l.votes and #w.transfers = #l.transfers implies
			w.outcome = TiedWinner and 0 < #w.votes + #w.transfers and
			(l.outcome = TiedLoser or l.outcome = TiedEarlyLoser or l.outcome = TiedSoreLoser)
}

// Highest winner has a quota
fact highestWinners {
   all c: Candidate | Election.method = STV and c.outcome = Winner implies
		Scenario.quota <= #c.votes + #c.transfers
}

// Tied Winners and Tied Losers have an equal number of votes
fact equalTies {
	all disj a,b: Candidate | a.outcome = TiedWinner and
        (b.outcome = TiedLoser or b.outcome = TiedEarlyLoser or b.outcome = TiedSoreLoser) implies
		#a.votes + #a.transfers = #b.votes + #b.transfers
}

// Winners have more votes than non-tied losers
fact winnersHaveVotes {
	all w,l: Candidate | w.outcome = Winner and
      (l.outcome = Loser or l.outcome = EarlyLoser or l.outcome = SoreLoser) implies
     ((#l.votes < #w.votes) or (#l.votes + #l.transfers < #w.votes + #w.transfers))
}

// All non-sore losers are above the threshold
fact losersAboveThreshold {
  all c: Candidate | c.outcome = Loser implies (Scenario.threshold < #c.votes + #c.transfers)
}

fact earlyLosersAboveThreshold {
  all c: Candidate | c.outcome = EarlyLoser implies (Scenario.threshold < #c.votes + #c.transfers)
}

fact tiedLosersAboveThreshold {
  all c: Candidate | c.outcome = TiedLoser implies (Scenario.threshold < #c.votes + #c.transfers)
}

fact tiedEarlyLosersAboveThreshold {
  all c: Candidate | c.outcome = TiedEarlyLoser implies (Scenario.threshold < #c.votes + #c.transfers)
}

-- Basic Lemmas
assert honestCount {
	  all c: Candidate | all b: Ballot | b in c.votes + c.transfers implies c in b.assignees
}
check honestCount for 15 but 6 int

assert atLeastOneLoser {
	0 < #Scenario.losers
}
check atLeastOneLoser for 15 but 6 int

assert atLeastOneWinner {
	0 < #Scenario.winners
}
check atLeastOneWinner for 14 but 6 int

assert plurality {
	all c: Candidate | all b: Ballot | b in c.votes and
		Election.method = Plurality implies c in b.preferences.first
}
check plurality for 18 but 6 int

assert wellFormedTieBreaker {
	some w,l : Candidate | (w in Scenario.winners and l in Scenario.losers and
		#w.votes = #l.votes and #w.transfers = #l.transfers) implies
		w.outcome = TiedWinner and
		(l.outcome = TiedLoser or l.outcome = TiedSoreLoser or l.outcome=TiedEarlyLoser)
}
check wellFormedTieBreaker for 18 but 6 int

assert validSurplus {
	all c: Candidate | 0 < #c.surplus implies (c.outcome = Winner or c.outcome = QuotaWinner or
		c in Scenario.eliminated)
}
check validSurplus for 16 but 6 int

-- Advanced Lemmas
// No lost votes during counting
assert accounting {
	all b: Ballot | some c: Candidate | b in c.votes and c in b.assignees
}
check accounting for 16 but 6 int

// Cannot have tie breaker with both tied sore loser and non-sore loser
assert tiedWinnerLoserTiedSoreLoser {
	no disj c,w,l: Candidate | c.outcome = TiedSoreLoser and
	   w.outcome = TiedWinner and (l.outcome = Loser or l.outcome = TiedLoser)
}
check tiedWinnerLoserTiedSoreLoser for 6 int

// Compromise winner must have at least one vote
assert validCompromise {
	all c: Candidate | c.outcome = CompromiseWinner implies 0 < #c.votes + #c.transfers
}
check validCompromise for 6 int

// Quota not more than the number of ballots cast
assert maxQuota {
  Scenario.quota <= #Ballot
}
check maxQuota for 7 int

// Quota winner needs transfers
assert quotaWinnerNeedsTransfers {
  all c: Candidate | c.outcome = QuotaWinner implies 0 < #c.transfers
}
check quotaWinnerNeedsTransfers for 7 int

// Sore losers below threshold
assert soreLoserBelowThreshold {
  all c: Candidate | c.outcome = SoreLoser implies not (Scenario.threshold <= #c.votes + #c.transfers)
}
check soreLoserBelowThreshold for 10 but 6 int

// Possible outcomes when under the threshold
assert underThresholdOutcomes {
  all c: Candidate | (#c.votes + #c.transfers < Scenario.threshold) implies
     (c.outcome = SoreLoser or c.outcome = TiedSoreLoser or c.outcome = TiedWinner or
     c.outcome = CompromiseWinner or (Election.method = Plurality and c.outcome = Winner))
}
check underThresholdOutcomes for 10 but 6 int

// Non-sore loser gets at least one vote
assert zeroVote {
  all c: Candidate | (#c.votes + #c.transfers = 0) implies (c.outcome = SoreLoser)
}
check zeroVote for 10 but 6 int

// Tied Winners have equality of votes and transfers
assert tiedWinnerEquality {
  all a,b: Candidate | (a.outcome = TiedWinner and b.outcome = TiedWinner) implies
	#a.votes + #a.transfers = #b.votes + #b.transfers
}
check tiedWinnerEquality for 10 but 6 int

// Non-negative threshold and quota
assert nonNegativeThresholdAndQuota {
	0 <= Scenario.threshold and Scenario.threshold <= Scenario.quota
}
check nonNegativeThresholdAndQuota for 6 but 6 int

-- Sample scenarios
pred TwoCandidatePlurality {
	Election.method = Plurality
	Election.seats = 1
	#Election.candidates = 2
}
run TwoCandidatePlurality for 10 but 2 Ballot, 6 int

pred PluralityTiedWinner {
	Election.method = Plurality
	Election.seats = 1
	some disj a,b: Candidate | a.outcome = TiedWinner and b.outcome = TiedLoser
}
run PluralityTiedWinner for 10 but 6 int

pred ThreeCandidatePlurality {
	Election.method = Plurality
	Election.seats = 1
	#Election.candidates = 3
}
run ThreeCandidatePlurality for 6 int

pred Plurality {
	Election.method = Plurality
	Election.seats = 1
	3 < #Election.candidates
}
run Plurality for 5 but 6 int

pred TenCandidatePluralityWithTwoSeats {
	Election.method = Plurality
	Election.seats = 2
	#Election.candidates = 10
}
run TenCandidatePluralityWithTwoSeats for 10 but 6 int

pred InstantRunoffVoting {
	Election.method = STV
	Election.seats = 1
	3 < #Election.candidates
}
run InstantRunoffVoting for 10 but 6 int

pred STV3 {
	Election.method = STV
	Election.seats = 3
}
run STV3 for 5 but 6 int

pred ThreeWinnersOneLoser {
    Election.method = STV
	some disj a,b,d: Candidate | a.outcome = Winner
   	  and b.outcome = QuotaWinner or b.outcome = CompromiseWinner
	  and d in Scenario.losers
}
run ThreeWinnersOneLoser for 6 but 6 int

pred LoserAndEarlyLoser {
	one d: Candidate | d.outcome = Loser
	one e: Candidate | e.outcome = EarlyLoser
}
run LoserAndEarlyLoser for 5 but 6 int

pred OneWinnerNineLosers {
	#Scenario.winners = 1
	#Scenario.losers = 9
}
run OneWinnerNineLosers for 16 but 6 int

pred ThreeWayTie {
	#Election.candidates = 3
    Election.method = Plurality
	some disj a,b,c: Candidate | a.outcome = TiedWinner and
		b.outcome = TiedLoser and
		c.outcome = TiedLoser
}
run ThreeWayTie for 10 but 6 int

pred FiveWayTie {
	some disj a,b,c,d,e: Candidate | a.outcome = TiedWinner and
	    b.outcome = TiedLoser and
		c.outcome = TiedLoser and d.outcome = TiedLoser and e.outcome = TiedWinner
}
run FiveWayTie for 7 but 6 int

pred ScenarioLWW {
	some disj a,b,c: Candidate | a.outcome = Loser and b.outcome = Winner and
		c.outcome = Winner
    #Election.candidates = 3
	Election.method = STV
    0 < #Ballot
}
run ScenarioLWW for 7 but 7 int

pred LongBallot {
	some b: Ballot | #b.preferences = 7
}
run LongBallot for 7 but 6 int

pred MultipleBallotsUnderSTV {
	Election.method = STV
	some disj a,b,c,d: Ballot | 1 < #a.preferences and 1 < #b.preferences
	and 0 < #c.preferences and 0 < #d.preferences and
        a.preferences.first = b.preferences.last
}
run MultipleBallotsUnderSTV for 10 but 6 int

pred WinnerLoserEarlyLoser {
	some a,b,c,d : Candidate | a.outcome = Winner and b.outcome = Loser and
		c.outcome = EarlyLoser and d.outcome = SoreLoser
	Election.method = STV
}
run WinnerLoserEarlyLoser for 7 but 6 int

pred TiedScenario {
  some disj a,b: Candidate | a.outcome = TiedLoser and b.outcome = TiedWinner
     Election.method = STV
     #Election.candidates = 2
     #Election.seats = 1
}
run TiedScenario for 7 but 6 int

pred NoTiesAndNoSoresScenarios {
  Election.method = STV
  #Election.candidates > 3
  #Ballot > 6
  no c: Candidate | c.outcome = TiedLoser or c.outcome = TiedWinner or
    c.outcome = TiedEarlyLoser or c.outcome = TiedSoreLoser or c.outcome = SoreLoser
}
run NoTiesAndNoSoresScenarios for 10 but 6 int

-- Scenario tests
pred SLW {
  some disj c0,c1,d: Candidate | c0.outcome = Loser and c1.outcome = Winner and
  d.outcome = SoreLoser and
  Election.method = Plurality and #Election.candidates = 3
  Scenario.threshold = 1
}
run SLW for 6 but 6 int

pred SSSLW {
  some disj c0,c1,d,e,f: Candidate | c0.outcome = Loser and c1.outcome = Winner and
  d.outcome = SoreLoser and
  e.outcome = SoreLoser and
  f.outcome = SoreLoser and
  Election.method = Plurality and #Election.candidates = 5
}
run SSSLW for 6 but 6 int

pred SSSSLW {
  some disj c0,c1,d,e,f,g: Candidate | c0.outcome = Loser and c1.outcome = Winner and
  d.outcome = SoreLoser and
  e.outcome = SoreLoser and
  f.outcome = SoreLoser and
  g.outcome = SoreLoser and
  Election.method = Plurality and #Election.candidates = 6
}
run SSSSLW for 6 but 6 int

pred LW {
  some disj c0,c1: Candidate | c0.outcome = Loser and c1.outcome = Winner and
  Election.method = Plurality and 0 < #Ballot and #Election.candidates = 2
}
run LW for 5 but 6 int

pred LQ {
	some disj a,b: Candidate | a.outcome = Loser and b.outcome = QuotaWinner
    #Election.candidates = 2
    0 < #Ballot
}
run LQ for 10 but 6 int

pred LQQ {
	some disj a,b,c: Candidate | a.outcome = Loser and b.outcome = QuotaWinner and
       c.outcome = QuotaWinner
    #Election.candidates = 3
    0 < #Ballot
}
run LQQ for 10 but 6 int

pred LQW {
	some disj a,b,c: Candidate | a.outcome = Loser and b.outcome = QuotaWinner and
		c.outcome = Winner
    #Election.candidates = 3
    0 < #Ballot
}
run LQW for 10 but 6 int

pred LQQW {
	some disj a,b,c,d: Candidate | a.outcome = Loser and b.outcome = QuotaWinner and
		c.outcome = Winner and d.outcome = QuotaWinner
    #Election.candidates = 4
    0 < #Ballot
}
run LQQW for 10 but 6 int

pred SLQQW {
	some disj a,b,c,d,e: Candidate | a.outcome = Loser and b.outcome = QuotaWinner and
		c.outcome = Winner and d.outcome = QuotaWinner and e.outcome = SoreLoser
    #Election.candidates = 5
    0 < #Ballot
}

pred tenCandidates {
  some disj c0,c1,c2,c3,c4,c5,c6,c7,c8,c9: Candidate | c0.outcome = SoreLoser and
    c1.outcome = SoreLoser and c2.outcome = SoreLoser and c3.outcome = Loser and
    c4.outcome = Loser and c5.outcome = Loser and c6.outcome = Loser and
    c7.outcome = TiedLoser and c8.outcome = TiedLoser and c9.outcome = TiedWinner and
    Election.method = Plurality and 1 < #Ballot and #Election.candidates = 10
}
run tenCandidates for 30 but 7 int

-- Version Control for changes to model
one sig Version {
   year, month, day: Int
} {
  year = 11
  month = 01
  day = 25
  -- Dermot Cochran 2011-01-25
}

-- (c) 2010-2011, Dermot Cochran, IT University of Copenhagen
-- http://www.kindsoftware.com/about/people/dc
-- http://www.itu.dk/people/dero

module Voting

open util/integer

-- An individual person standing for election
sig Candidate {
    votes: 			  set Ballot, 	-- First preference ballots assigned to this candidate
	transfers: 	      set Ballot,   -- Ballots received by transfer from another candidate
	surplus: 		  set Ballot, 	-- Ballots given to another candidate (on election or elimination)
	outcome: 		  Event
} {
	no b: Ballot | b in votes & transfers
	all b: Ballot | b in votes + transfers implies this in b.assignees
	surplus in votes + transfers
	Election.method = Plurality implies #surplus = 0 and #transfers = 0
}

-- A digital or paper artifact which accurately records the intentions of the voter
sig Ballot {
  assignees: 		set Candidate,  -- Candidates to which this ballot has been assigned
  preferences: 	seq Candidate  -- Ranking of candidates
} {
	assignees in preferences.elems
    not preferences.hasDups
	preferences.elems in Election.candidates
	preferences.first in assignees
	Election.method = Plurality implies #preferences = 1
    0 < #preferences
}

-- An election result
one sig Scenario {
   	losers: 				set Candidate,
   	winners: 			set Candidate,
	eliminated: 		set Candidate, 		-- Early and Sore Losers under STV rules
	threshold: 		Int, 						-- Minimum number of votes for a Loser or Early Loser
	quota: 				Int						-- Minimum number of votes for a STV Winner or Quota Winner
}
{
 	winners + losers = Election.candidates
 	#winners = Election.seats
 	no c: Candidate | c in losers & winners
 	0 < #losers
 	all w: Candidate | all l: Candidate | l in losers and w in winners implies
		((#l.votes + #l.transfers <= #w.votes + #w.transfers) and (#l.votes <= #w.votes))
    threshold = 1 + quota.div[4]
	Election.method = Plurality implies #eliminated = 0
	eliminated in losers
	all c: Candidate | c in losers implies Election.method = Plurality
       or #c.votes + #c.transfers < quota
}

/*
	There are four winner-outcomes and six loser-outcomes:

	Winner: 						(W1) elected in the first round of counting either by quota or plurality,
	QuotaWinner: 				(W2) elected with transfers from another candidate (STV only),
	CompromiseWinner: 	(W3) elected on the last round of counting without quota (STV only),
	TiedWinner:					(W4) elected by tie breaker,
	TiedLoser:					(L1) loses only by tie breaker but reaches the threshold,
	Loser:			 				(L2) defeated on last round but reaches the minimum threshold of votes,
    TiedEarlyLoser:			(L3) reaches threshold but eliminated by tie breaker (STV only),
	EarlyLoser:					(L4) reaches threshold but is eliminated before last round (STV only),
	TiedSoreLoser:				(L5) loses only by tie breaker but does not reach threshold,
	SoreLoser: 					(L6) does not even reach the mimimum threshold of votes.
*/
enum Event {Winner, QuotaWinner, CompromiseWinner, TiedWinner,
	TiedLoser, Loser, TiedEarlyLoser, EarlyLoser, TiedSoreLoser, SoreLoser}

enum Method {Plurality, STV}

-- An Election Constituency
one sig Election {
  candidates: 	set Candidate,
  seats: 				Int,
  method: 			Method,
  ballots:			Int -- number of ballots cast
}
{
 	0 < seats
 	seats < #candidates
 	all c: Candidate | c in candidates
    ballots = #Ballot
    Scenario.quota = 1 + ballots.div[seats+1]
}

-- Independent (or Fundamental) Axioms

fact surplus {
  all c: Candidate | (c.outcome = Winner and Election.method = STV) implies
     Scenario.quota + #c.surplus = #c.votes
}

fact winnersWithoutTransfers {
  all c: Candidate | (c.outcome = Winner and Election.method = STV) implies #c.transfers = 0
}

fact surplusFromTransfers {
  all c: Candidate | c.outcome = QuotaWinner implies ((surplus in transfers) and
     ((Scenario.quota + #c.surplus) = (#c.votes + #c.transfers)))
}

fact integrity {
  all c: Candidate | all b: Ballot | b in c.votes implies c in b.assignees
}

fact pluralityEvents {
	all c: Candidate | Election.method = Plurality implies
		(c.outcome = Loser or c.outcome = SoreLoser or c.outcome = Winner or
		c.outcome = TiedWinner or c.outcome = TiedLoser)
}

fact winnerSTV {
	all c: Candidate | (Election.method = STV and c.outcome = Winner) implies
       Scenario.quota <= #c.votes
}

fact transferWinnerWithQuota {
	all c: Candidate | (Election.method = STV and c.outcome = QuotaWinner) implies
	   Scenario.quota <= #c.votes + #c.transfers
}

fact transferWinnerNotFirst {
	all c: Candidate |  (Election.method = STV and c.outcome = QuotaWinner) implies
		not Scenario.quota <= #c.votes
}

fact closeWinner {
	all c: Candidate | (c.outcome = CompromiseWinner or c.outcome = TiedWinner) implies
		not (Scenario.quota <= #c.votes + #c.transfers) or Election.method = Plurality
}

fact soreLoser {
	all c: Candidate | (c.outcome = SoreLoser or c.outcome = TiedSoreLoser) implies
		((#c.votes + #c.transfers) < Scenario.threshold)
}

fact loser {
	all c: Candidate | (c.outcome = Loser or c.outcome = TiedLoser)
        implies (c in Scenario.losers and c not in Scenario.eliminated)
}

fact earlyLoser {
	all c: Candidate | (c.outcome = EarlyLoser or c.outcome = TiedEarlyLoser) iff
		(c in Scenario.eliminated and not (#c.votes + #c.transfers < Scenario.threshold))
}

fact winners {
	all c: Candidate | c in Scenario.winners iff
		(c.outcome = Winner or c.outcome = QuotaWinner or c.outcome = CompromiseWinner or
		c.outcome = TiedWinner)
}

fact losers {
	all c: Candidate | c in Scenario.losers iff
		(c.outcome = Loser or c.outcome = EarlyLoser or c.outcome = SoreLoser or
		c.outcome = TiedLoser or c.outcome = TiedEarlyLoser or c.outcome = TiedSoreLoser)
}

-- Non-Independent Axioms for Ballot Integrity
fact transfers {
	all c: Candidate | 0 < #c.transfers implies Election.method = STV
}

fact onlyWinnersAndQuotaWinnersHaveSurplus {
	all c: Candidate | 0 < #c.surplus implies
		(c.outcome = Winner or c.outcome = QuotaWinner)
}

fact winnersNeedNoTransfers {
		all c: Candidate | c.outcome = Winner implies 0 = #c.transfers
}

fact firstPreference {
	all b: Ballot | all c: Candidate | b.preferences.first = c iff b in c.votes
}

fact sizeOfSurplus {
	all c: Candidate | (c in Scenario.winners and Election.method = STV and 0 < #c.surplus) implies
		(#c.surplus = #c.votes + #c.transfers - Scenario.quota)
}

fact transferToNextPreference {
	all b: Ballot | all disj donor,receiver: Candidate |
		(donor + receiver in b.assignees and
		b in receiver.transfers and b in donor.surplus) implies
		(b.preferences.idxOf[donor] < b.preferences.idxOf[receiver] and
		receiver in b.preferences.rest.elems)
}

fact pluralityWinner {
	all disj a, b: Candidate | (Election.method = Plurality and Election.seats = 1 and
		a.outcome = Winner) implies #b.votes <= #a.votes
}

fact transferToNextContinuingCandidate {
	all disj skipped, receiving: Candidate | all b: Ballot |
		b.preferences.idxOf[skipped] < b.preferences.idxOf[receiving] and
		receiving in b.assignees and (not skipped in b.assignees) implies
		(skipped in Scenario.eliminated or skipped.outcome = Winner or
		skipped.outcome = QuotaWinner)
}

// All ballot transfers are associated with the last candidate to receive the transfer
fact ownership {
	all disj c,d: Candidate | all b: Ballot | b in c.transfers implies c in b.assignees and
		(d not in b.assignees or b.preferences.idxOf[d] < b.preferences.idxOf[c])
}

// Lowest candidate is eliminated first
fact lowestElimination {
	all disj c,d: Candidate | c in Scenario.eliminated and d not in Scenario.eliminated implies
		#c.votes + #c.transfers <= #d.votes + #d.transfers
}

// All ties involve equality between at least one winner and at least one loser on either original votes or
// on transfers plus original votes
fact equalityOfTiedWinner {
   all w: Candidate | some l: Candidate | w.outcome = TiedWinner and
	 	(l.outcome = TiedLoser or l.outcome = TiedSoreLoser or l.outcome = TiedEarlyLoser) implies
		(#l.votes = #w.votes) or (#l.votes + #l.transfers = #w.votes + #w.transfers)
}

fact equalityOfTiedLosers {
  all s: Candidate | some w: Candidate | w.outcome = TiedWinner and
       (s.outcome = SoreLoser or s.outcome = TiedLoser or s.outcome = TiedEarlyLoser) implies
       (#s.votes = #w.votes) or (#s.votes + #s.transfers = #w.votes + #w.transfers)
}

-- Scenario Validity Axioms
// When there is a tied sore loser then there are no non-sore losers
fact typeOfTiedLoser {
   no disj a,b: Candidate | a.outcome = TiedSoreLoser and
        (b.outcome = TiedLoser or b.outcome = TiedEarlyLoser or
         b.outcome=Loser or b.outcome=EarlyLoser)
}

fact tieBreaker {
	all w: Candidate | some l: Candidate | w.outcome = TiedWinner implies
		(l.outcome = TiedLoser or l.outcome = TiedSoreLoser or l.outcome = TiedEarlyLoser)
}

fact validTieBreaker {
	all l: Candidate | some w: Candidate |
    (l.outcome = TiedLoser or l.outcome = TiedSoreLoser or l.outcome = TiedEarlyLoser) implies
    w.outcome = TiedWinner and (#w.votes + #w.transfers = #l.votes + #l.transfers)
}

// Compromise winner must have more votes than any tied winners
fact compromiseNotTied {
	all disj c,t: Candidate | (c.outcome = CompromiseWinner and t.outcome = TiedWinner) implies
		#t.votes + #t.transfers < #c.votes + #c.transfers
}

// Equal losers are tied
fact equalityofTiedWinnersAndLosers {
	all disj w,l: Candidate | w in Scenario.winners and l in Scenario.losers and
		#w.votes = #l.votes and #w.transfers = #l.transfers implies
			w.outcome = TiedWinner and 0 < #w.votes + #w.transfers and
			(l.outcome = TiedLoser or l.outcome = TiedEarlyLoser or l.outcome = TiedSoreLoser)
}

// Highest winner has a quota
fact highestWinners {
   all c: Candidate | Election.method = STV and c.outcome = Winner implies
		Scenario.quota <= #c.votes + #c.transfers
}

// Tied Winners and Tied Losers have an equal number of votes
fact equalTies {
	all disj a,b: Candidate | a.outcome = TiedWinner and
        (b.outcome = TiedLoser or b.outcome = TiedEarlyLoser or b.outcome = TiedSoreLoser) implies
		#a.votes = #b.votes and #a.transfers = #b.transfers
}

// Winners have more votes than non-tied losers
fact winnersHaveVotes {
	all w,l: Candidate | w.outcome = Winner and
      (l.outcome = Loser or l.outcome = EarlyLoser or l.outcome = SoreLoser) implies
     ((#l.votes < #w.votes) or (#l.votes + #l.transfers < #w.votes + #w.transfers))
}

// All non-sore losers are above the threshold
fact losersAboveThreshold {
  all c: Candidate | c.outcome = Loser implies (Scenario.threshold < #c.votes + #c.transfers)
}

fact earlyLosersAboveThreshold {
  all c: Candidate | c.outcome = EarlyLoser implies (Scenario.threshold < #c.votes + #c.transfers)
}

fact tiedLosersAboveThreshold {
  all c: Candidate | c.outcome = TiedLoser implies (Scenario.threshold < #c.votes + #c.transfers)
}

fact tiedEarlyLosersAboveThreshold {
  all c: Candidate | c.outcome = TiedEarlyLoser implies (Scenario.threshold < #c.votes + #c.transfers)
}

-- Basic Lemmas
assert honestCount {
	  all c: Candidate | all b: Ballot | b in c.votes + c.transfers implies c in b.assignees
}
check honestCount for 15 but 6 int

assert atLeastOneLoser {
	0 < #Scenario.losers
}
check atLeastOneLoser for 15 but 6 int

assert atLeastOneWinner {
	0 < #Scenario.winners
}
check atLeastOneWinner for 14 but 6 int

assert plurality {
	all c: Candidate | all b: Ballot | b in c.votes and
		Election.method = Plurality implies c in b.preferences.first
}
check plurality for 18 but 6 int

assert wellFormedTieBreaker {
	some w,l : Candidate | (w in Scenario.winners and l in Scenario.losers and
		#w.votes = #l.votes and #w.transfers = #l.transfers) implies
		w.outcome = TiedWinner and
		(l.outcome = TiedLoser or l.outcome = TiedSoreLoser or l.outcome=TiedEarlyLoser)
}
check wellFormedTieBreaker for 18 but 6 int

assert validSurplus {
	all c: Candidate | 0 < #c.surplus implies (c.outcome = Winner or c.outcome = QuotaWinner or
		c in Scenario.eliminated)
}
check validSurplus for 16 but 6 int

-- Advanced Lemmas
// No lost votes during counting
assert accounting {
	all b: Ballot | some c: Candidate | b in c.votes and c in b.assignees
}
check accounting for 16 but 6 int

// Cannot have tie breaker with both tied sore loser and non-sore loser
assert tiedWinnerLoserTiedSoreLoser {
	no disj c,w,l: Candidate | c.outcome = TiedSoreLoser and
	   w.outcome = TiedWinner and (l.outcome = Loser or l.outcome = TiedLoser)
}
check tiedWinnerLoserTiedSoreLoser for 6 int

// Compromise winner must have at least one vote
assert validCompromise {
	all c: Candidate | c.outcome = CompromiseWinner implies 0 < #c.votes + #c.transfers
}
check validCompromise for 6 int

// Quota not more than the number of ballots cast
assert maxQuota {
  Scenario.quota <= #Ballot
}
check maxQuota for 7 int

// Quota winner needs transfers
assert quotaWinnerNeedsTransfers {
  all c: Candidate | c.outcome = QuotaWinner implies 0 < #c.transfers
}
check quotaWinnerNeedsTransfers for 7 int

// Sore losers below threshold
assert soreLoserBelowThreshold {
  all c: Candidate | c.outcome = SoreLoser implies not (Scenario.threshold <= #c.votes + #c.transfers)
}
check soreLoserBelowThreshold for 10 but 6 int

// Possible outcomes when under the threshold
assert underThresholdOutcomes {
  all c: Candidate | (#c.votes + #c.transfers < Scenario.threshold) implies
     (c.outcome = SoreLoser or c.outcome = TiedSoreLoser or c.outcome = TiedWinner or
     c.outcome = CompromiseWinner or (Election.method = Plurality and c.outcome = Winner))
}
check underThresholdOutcomes for 10 but 6 int

// Non-sore loser gets at least one vote
assert zeroVote {
  all c: Candidate | (#c.votes + #c.transfers = 0) implies (c.outcome = SoreLoser)
}
check zeroVote for 10 but 6 int

// Tied Winners have equality of votes and transfers
assert tiedWinnerEquality {
  all a,b: Candidate | (a.outcome = TiedWinner and b.outcome = TiedWinner) implies
	#a.votes + #a.transfers = #b.votes + #b.transfers
}
check tiedWinnerEquality for 10 but 6 int

// Non-negative threshold and quota
assert nonNegativeThresholdAndQuota {
	0 <= Scenario.threshold and Scenario.threshold <= Scenario.quota
}
check nonNegativeThresholdAndQuota for 6 but 6 int

-- Sample scenarios
pred TwoCandidatePlurality {
	Election.method = Plurality
	Election.seats = 1
	#Election.candidates = 2
}
run TwoCandidatePlurality for 10 but 2 Ballot, 6 int

pred PluralityTiedWinner {
	Election.method = Plurality
	Election.seats = 1
	some disj a,b: Candidate | a.outcome = TiedWinner and b.outcome = TiedLoser
}
run PluralityTiedWinner for 10 but 6 int

pred ThreeCandidatePlurality {
	Election.method = Plurality
	Election.seats = 1
	#Election.candidates = 3
}
run ThreeCandidatePlurality for 6 int

pred Plurality {
	Election.method = Plurality
	Election.seats = 1
	3 < #Election.candidates
}
run Plurality for 5 but 6 int

pred TenCandidatePluralityWithTwoSeats {
	Election.method = Plurality
	Election.seats = 2
	#Election.candidates = 10
}
run TenCandidatePluralityWithTwoSeats for 10 but 6 int

pred InstantRunoffVoting {
	Election.method = STV
	Election.seats = 1
	3 < #Election.candidates
}
run InstantRunoffVoting for 10 but 6 int

pred STV3 {
	Election.method = STV
	Election.seats = 3
}
run STV3 for 5 but 6 int

pred ThreeWinnersOneLoser {
    Election.method = STV
	some disj a,b,d: Candidate | a.outcome = Winner
   	  and b.outcome = QuotaWinner or b.outcome = CompromiseWinner
	  and d in Scenario.losers
}
run ThreeWinnersOneLoser for 6 but 6 int

pred LoserAndEarlyLoser {
	one d: Candidate | d.outcome = Loser
	one e: Candidate | e.outcome = EarlyLoser
}
run LoserAndEarlyLoser for 5 but 6 int

pred OneWinnerNineLosers {
	#Scenario.winners = 1
	#Scenario.losers = 9
}
run OneWinnerNineLosers for 16 but 6 int

pred ThreeWayTie {
	#Election.candidates = 3
    Election.method = Plurality
	some disj a,b,c: Candidate | a.outcome = TiedWinner and
		b.outcome = TiedLoser and
		c.outcome = TiedLoser
}
run ThreeWayTie for 10 but 6 int

pred FiveWayTie {
	some disj a,b,c,d,e: Candidate | a.outcome = TiedWinner and
	    b.outcome = TiedLoser and
		c.outcome = TiedLoser and d.outcome = TiedLoser and e.outcome = TiedWinner
}
run FiveWayTie for 7 but 6 int

pred ScenarioLWW {
	some disj a,b,c: Candidate | a.outcome = Loser and b.outcome = Winner and
		c.outcome = Winner
    #Election.candidates = 3
	Election.method = STV
    0 < #Ballot
}
run ScenarioLWW for 7 but 7 int

pred LongBallot {
	some b: Ballot | #b.preferences = 7
}
run LongBallot for 7 but 6 int

pred MultipleBallotsUnderSTV {
	Election.method = STV
	some disj a,b,c,d: Ballot | 1 < #a.preferences and 1 < #b.preferences
	and 0 < #c.preferences and 0 < #d.preferences and
        a.preferences.first = b.preferences.last
}
run MultipleBallotsUnderSTV for 10 but 6 int

pred WinnerLoserEarlyLoser {
	some a,b,c,d : Candidate | a.outcome = Winner and b.outcome = Loser and
		c.outcome = EarlyLoser and d.outcome = SoreLoser
	Election.method = STV
}
run WinnerLoserEarlyLoser for 7 but 6 int

pred TiedScenario {
  some disj a,b: Candidate | a.outcome = TiedLoser and b.outcome = TiedWinner
     Election.method = STV
     #Election.candidates = 2
     #Election.seats = 1
}
run TiedScenario for 7 but 6 int

pred NoTiesAndNoSoresScenarios {
  Election.method = STV
  #Election.candidates > 3
  #Ballot > 6
  no c: Candidate | c.outcome = TiedLoser or c.outcome = TiedWinner or
    c.outcome = TiedEarlyLoser or c.outcome = TiedSoreLoser or c.outcome = SoreLoser
}
run NoTiesAndNoSoresScenarios for 10 but 6 int

-- Scenario tests
pred SLW {
  some disj c0,c1,d: Candidate | c0.outcome = Loser and c1.outcome = Winner and
  d.outcome = SoreLoser and
  Election.method = Plurality and #Election.candidates = 3
  Scenario.threshold = 1
}
run SLW for 6 but 6 int

pred SSSLW {
  some disj c0,c1,d,e,f: Candidate | c0.outcome = Loser and c1.outcome = Winner and
  d.outcome = SoreLoser and
  e.outcome = SoreLoser and
  f.outcome = SoreLoser and
  Election.method = Plurality and #Election.candidates = 5
}
run SSSLW for 6 but 6 int

pred SSSSLW {
  some disj c0,c1,d,e,f,g: Candidate | c0.outcome = Loser and c1.outcome = Winner and
  d.outcome = SoreLoser and
  e.outcome = SoreLoser and
  f.outcome = SoreLoser and
  g.outcome = SoreLoser and
  Election.method = Plurality and #Election.candidates = 6
}
run SSSSLW for 6 but 6 int

pred LW {
  some disj c0,c1: Candidate | c0.outcome = Loser and c1.outcome = Winner and
  Election.method = Plurality and 0 < #Ballot and #Election.candidates = 2
}
run LW for 5 but 6 int

pred LQ {
	some disj a,b: Candidate | a.outcome = Loser and b.outcome = QuotaWinner
    #Election.candidates = 2
    0 < #Ballot
}
run LQ for 10 but 6 int

pred LQQ {
	some disj a,b,c: Candidate | a.outcome = Loser and b.outcome = QuotaWinner and
       c.outcome = QuotaWinner
    #Election.candidates = 3
    0 < #Ballot
}
run LQQ for 10 but 6 int

pred LQW {
	some disj a,b,c: Candidate | a.outcome = Loser and b.outcome = QuotaWinner and
		c.outcome = Winner
    #Election.candidates = 3
    0 < #Ballot
}
run LQW for 10 but 6 int

pred LQQW {
	some disj a,b,c,d: Candidate | a.outcome = Loser and b.outcome = QuotaWinner and
		c.outcome = Winner and d.outcome = QuotaWinner
    #Election.candidates = 4
    0 < #Ballot
}
run LQQW for 10 but 6 int

pred SLQQW {
	some disj a,b,c,d,e: Candidate | a.outcome = Loser and b.outcome = QuotaWinner and
		c.outcome = Winner and d.outcome = QuotaWinner and e.outcome = SoreLoser
    #Election.candidates = 5
    0 < #Ballot
}

pred tenCandidates {
  some disj c0,c1,c2,c3,c4,c5,c6,c7,c8,c9: Candidate | c0.outcome = SoreLoser and
  c1.outcome = SoreLoser and c2.outcome = SoreLoser and c3.outcome = Loser and
  c4.outcome = Loser and c5.outcome = Loser and c6.outcome = Loser and
  c7.outcome = TiedLoser and c8.outcome = TiedLoser and c9.outcome = TiedWinner and
  Election.method = Plurality and 1 < #Ballot and #Election.candidates = 10
}
run tenCandidates for 13 but 7 int

-- Version Control for changes to model
one sig Version {
   year, month, day: Int
} {
  year = 11
  month = 01
  day = 24
  -- Dermot Cochran 2011-01-24
}


adding hint

adding hint

module exec_ptx[E]
open exec_H[E]

sig Exec_PTX extends Exec_H {
  scta, sgl : E->E // same CTA, same global
}{

  // scta and sgl are equivalence relations among all events
  is_equivalence[scta, ev]
  is_equivalence[sgl, ev]

  // Same thread implies same cta
  sthd in scta

  // Same CTA implies same global
  scta in sgl

  // There are no RMW events, instead we use the atom relation
  // to link the R and the W events
  no (R&W)

  // Atom relation not done yet
  no atom

}

pred wf_Exec_PTX[X:Exec_PTX, ad,cd,dd,membar_cta,membar_gl,membar_sys:E->E] {

  wf_Exec_H[X,ad,cd,dd]

  is_fence_rel[membar_sys, X.sb]
  is_fence_rel[membar_gl, X.sb]
  is_fence_rel[membar_cta, X.sb]

  // A membar.sys implies a membar.gl, which implies a membar.cta
  membar_sys in membar_gl
  membar_gl in membar_cta

}

fun scta[e:E, X:Exec_PTX, ad,cd,dd,membar_cta,membar_gl,membar_sys:E->E] : E->E { X.scta - (univ -> e) - (e -> univ) }
fun sgl[e:E, X:Exec_PTX, ad,cd,dd,membar_cta,membar_gl,membar_sys:E->E] : E->E { X.sgl - (univ -> e) - (e -> univ) }
fun membar_sys[e:E, X:Exec_PTX, ad,cd,dd,membar_cta,membar_gl,membar_sys:E->E] : E->E { membar_sys - (univ -> e) - (e -> univ) }
fun membar_gl[e:E, X:Exec_PTX, ad,cd,dd,membar_cta,membar_gl,membar_sys:E->E] : E->E { membar_gl - (univ -> e) - (e -> univ) }
fun membar_cta[e:E, X:Exec_PTX, ad,cd,dd,membar_cta,membar_gl,membar_sys:E->E] : E->E { membar_cta - (univ -> e) - (e -> univ) }

// Synonyms
fun membarsys[e:E, X:Exec_PTX, ad,cd,dd,membar_cta,membar_gl,membar_sys:E->E] : E->E { membar_sys - (univ -> e) - (e -> univ) }
fun membargl[e:E, X:Exec_PTX, ad,cd,dd,membar_cta,membar_gl,membar_sys:E->E] : E->E { membar_gl - (univ -> e) - (e -> univ) }
fun membarcta[e:E, X:Exec_PTX, ad,cd,dd,membar_cta,membar_gl,membar_sys:E->E] : E->E { membar_cta - (univ -> e) - (e -> univ) }

/*
W y 2   R y 2       R x 1
        membar.gl   membar.cta
        W x 1       W y 1
*/


can marry with sister

can marry with sister

open util/ordering[Time]
open named_man_ja [Man]
open named_woman_ja [Woman]

sig Time {
	event: lone Event
}

fact {
	no first.event
	all t: Time - first {one t.event}
}

abstract sig Person {
	state: State -> Time,
	partner: Person -> Time,
	parent_bio: set Person,
  parent_think: set Person
}{
	all t: Time | one state.t
	all t: Time | lone partner.t
	let p = parent_bio {
		no p or born_in_scope
  }
	let p = parent_think {
		no p or born_in_scope
  }
}

pred born_in_scope(p: Person){
	p.state.first = NotExist
	p.state.last != NotExist
}

abstract sig Man, Woman extends Person {}

enum State {NotExist, Married, NotMarried}

enum Event {Marriage, Divorce, Birth}

pred init (t: Time) {
	all p: Person | p.state.t in NotMarried + NotExist
	all p: Person | p.partner.t = none
}

pred change_state (
	target : Person,
	t, t': Time,
	before, after : State){
		some target
		all p: target {
			p.state.t = before
			p.state.t' = after
		}
		// others don't change their state
		all other: (Person - target) {
			other.state.t = other.state.t'
		}
}

pred keep_partner(others: Person, t, t': Time){
	all other: others {
		other.partner.t = other.partner.t'
	}
}
pred step (t, t': Time) {
	{some disj p1 : Man, p2 : Woman {
		{
			t'.event = Marriage
			change_state[p1 + p2, t, t', NotMarried, Married]
			p1.partner.t' = p2
			p2.partner.t' = p1
			keep_partner[Person - p1 - p2, t, t']
		} or {
			t'.event = Divorce
			change_state[p1 + p2, t, t', Married, NotMarried]
			p1.partner.t' = none
			p2.partner.t' = none
			keep_partner[Person - p1 - p2, t, t']
		}
	}}
	or
	some p: Person {
		// birth
		t'.event = Birth
		change_state[p, t, t', NotExist, NotMarried]
		let father = p.parent_bio & Man {
			one father
			father.state.t != NotExist
		}
		let mother = p.parent_bio & Woman {
			one mother
			mother.state.t != NotExist
			let hasband = mother.partner.t {
				// p always think his biological mother is his mother
				// if mother married, p think mother's hasband is his father
				// no other person is tought as parent
				p.parent_think = mother + hasband
			}
		}
		keep_partner[Person, t, t']
	}
}

fact Traces {
	init[first]
	all t: Time - last {
		step[t, t.next]
	}
}

pred can_marry_think (from, to: Person){
	to not in from.^parent_think
	from not in to.^parent_think
	to not in from.parent_think.~parent_think
}

pred can_marry_bio (from, to: Person){
	to not in from.^parent_bio
	from not in to.^parent_bio
	to not in from.parent_bio.~parent_bio
}

run {
	some parent_bio
	some p1: Man, p2: Woman {
		not can_marry_think[p1, p2] and can_marry_bio[p1, p2]
		p2 in p1.parent_think.~parent_think
	}
} for 6 Person, 8 Time

open util/ordering[Time]
open named_man_ja [Man]
open named_woman_ja [Woman]

sig Time {
	event: lone Event
}

fact {
	no first.event
	all t: Time - first {one t.event}
}

abstract sig Person {
	state: State -> Time,
	partner: Person -> Time,
	parent_bio: set Person,
  parent_think: set Person
}{
	all t: Time | one state.t
	all t: Time | lone partner.t
	let p = parent_bio {
		no p or born_in_scope
  }
	let p = parent_think {
		no p or born_in_scope
  }
}

pred born_in_scope(p: Person){
	p.state.first = NotExist
	p.state.last != NotExist
}

abstract sig Man, Woman extends Person {}

enum State {NotExist, Married, NotMarried}

enum Event {Marriage, Divorce, Birth}

pred init (t: Time) {
	all p: Person | p.state.t in NotMarried + NotExist
	all p: Person | p.partner.t = none
}

pred change_state (
	target : Person,
	t, t': Time,
	before, after : State){
		some target
		all p: target {
			p.state.t = before
			p.state.t' = after
		}
		// others don't change their state
		all other: (Person - target) {
			other.state.t = other.state.t'
		}
}

pred keep_partner(others: Person, t, t': Time){
	all other: others {
		other.partner.t = other.partner.t'
	}
}
pred step (t, t': Time) {
	{some disj p1 : Man, p2 : Woman {
		{
			t'.event = Marriage
			change_state[p1 + p2, t, t', NotMarried, Married]
			p1.partner.t' = p2
			p2.partner.t' = p1
			keep_partner[Person - p1 - p2, t, t']
		} or {
			t'.event = Divorce
			change_state[p1 + p2, t, t', Married, NotMarried]
			p1.partner.t' = none
			p2.partner.t' = none
			keep_partner[Person - p1 - p2, t, t']
		}
	}}
	or
	some p: Person {
		// birth
		t'.event = Birth
		change_state[p, t, t', NotExist, NotMarried]
		let father = p.parent_bio & Man {
			one father
			father.state.t != NotExist
		}
		let mother = p.parent_bio & Woman {
			one mother
			mother.state.t != NotExist
			let hasband = mother.partner.t {
				// p always think his biological mother is his mother
				// if mother married, p think mother's hasband is his father
				// no other person is tought as parent
				p.parent_think = mother + hasband
			}
		}
		keep_partner[Person, t, t']
	}
}

fact Traces {
	init[first]
	all t: Time - last {
		step[t, t.next]
	}
}

pred can_marry_think (from, to: Person){
	to not in from.^parent_think
	from not in to.^parent_think
	to not in from.parent_think.~parent_think
}

pred can_marry_bio (from, to: Person){
	to not in from.^parent_bio
	from not in to.^parent_bio
	to not in from.parent_bio.~parent_bio
}

run {
	some parent_bio
	some p1: Man, p2: Woman {
		not can_marry_think[p1, p2] and can_marry_bio[p1, p2]
	}
} for 6 Person, 8 Time


Adding the file ta-assignment.als deleted by kacper, it's not a generated als file, but an example provided by Derek.

/* Simplifications:
    - for now we ignore lab instructors
    - for now we assume that a prof teaches only one course
    - profs only have three ranking levels in this model
    - we say TA's are happy if they get their first choice
    - no half TA positions
*/

-- the structure of the model (write by hand)
sig Course {
    lecturer : one Prof,
    assistants : set TA, -- this is what we are solving for
    allocation : one Int,
}{
    -- cannot have more TAs assigned than spaces allocated
    #assistants <= allocation
}
sig TA { first, second, third : lone Course }
sig Prof { prefer, reject : set TA }

-- constraints
-- each TA can be assigned to at most one course
fact SingleCoursePerTA { all ta : TA | lone assistants.ta }
-- TA will only be assigned to a course that they named
fact RespectTAWishes { ~assistants & (first+second+third) }
-- all assigned TAs are preferred or accepted by the prof
fact RespectProfWishes { no ~lecturer.assistants & reject }

-- this is generated from the CSV input
inst Winter2012 {
    Prof = X + Y,
    TA = A + B + C + D + E + F + G,
    Course = ECE155 + ECE351,
    lecturer = ECE155->X + ECE351->Y,
    allocation = ECE155->3 + ECE351->2,
    prefer = X->A + X->B + Y->A + Y->B + Y->C,
    reject = X->F + X->G + Y->D + Y->G,
    first = A->ECE155 + B->ECE351 + C->ECE155 + D->ECE351 + E->ECE155
            + F->ECE351 + G->ECE351
    second = A->ECE351 + B->ECE155 + C->ECE351 + D->ECE155 + E->ECE351
    no third
}

-- the various objectives to optimize
metrics m {
    -- prof happiness: got preferred TAs
    max[ #( ~lecturer.assistants & prefer ) ]
    -- prof unhappiness: spaces that are allocated by not assigned (holes)
    min[ (sum c : Course | c.allocation) - #assistants ]
    -- TA happiness: got first choice
    max[ #(assistants & ~first) ]
    -- TA unhappiness: didn't get a job
    min[ #(TA - Course.assistants) ]
}

pred p[] {}

run p for Winter2012 optimize m

error: pathspec 'test/suite/ta-assignment.als' did not match any file(s) known to git


by id:bonotake http://d.hatena.ne.jp/bonotake/20120413/1334300370

open util/ordering[Col] as cols
open util/ordering[Row] as rows

abstract sig Region {}
sig Col extends Region {
  cell: Row -> Cell
}
sig Row extends Region {}
enum Cell { Black, White }

fact {
  all c: Col, r: Row | one cell [c, r]
}

-- about rows
pred blackHeadInRow (c: Col, r: Row) {
  c in first or cell[c.prev, r] in White
  cell[c, r] in Black
}

fun headsInRow (r: Row): set Col {
  { c: Col | blackHeadInRow[c, r] }
}

fact noOtherHeadsInRow {
  no c: Col, r: Row | c not in headsInRow[r] and blackHeadInRow[c, r]
}

pred headsSeqInRow (r: Row, s: seq Col) {
  s.elems = headsInRow[r]
  all i: s.butlast.inds | lt [s[i], s[plus[i, 1]]]
}

fun Int2Row (i: Int): Row {
  {r: Row | #(r.prevs) = i}
}

fun Row2Int (r: Row): Int {
  #(r.prevs)
}

pred rowHint (j: Int, sizes: seq Int) {
  let r = Int2Row[j] | some cs: seq Col {
    #sizes = #cs
    headsSeqInRow [r, cs]
    all i: sizes.inds |
      let start = cs [i], end = Int2Col [plus [Col2Int [start], minus[sizes [i], 1] ]] {
       some end
       all c: start.*cols/next - end.^cols/next | cell [c, r] in Black
       no end.next or cell [end.next, r] in White
     }
  }
}

-- about cols
pred blackHeadInCol (c: Col, r: Row) {
  r in first or cell[c, r.prev] in White
  cell[c, r] in Black
}

fun headsInCol (c: Col): set Row {
  { r: Row | blackHeadInCol[c, r] }
}

fact noOtherHeadsInCol {
  no c: Col, r: Row | r not in headsInCol[c] and blackHeadInCol[c, r]
}

pred headsSeqInCol (c: Col, s: seq Row) {
  s.elems = headsInCol[c]
  all i: s.butlast.inds | lt [s[i], s[plus[i, 1]]]
}

fun Int2Col (i: Int): Col {
  {c: Col | #(c.prevs) = i}
}

fun Col2Int (c: Col): Int {
  #(c.prevs)
}

pred colHint (j: Int, sizes: seq Int) {
  let c = Int2Col[j] | some rs: seq Row {
    #sizes = #rs
    headsSeqInCol [c, rs]
    all i: sizes.inds |
      let start = rs [i], end = Int2Row [plus [Row2Int [start], minus[sizes [i], 1] ]] {
       some end
       all r: start.*rows/next - end.^rows/next | cell [c, r] in Black
       no end.next or cell [c, end.next] in White
     }
  }
}

-- riddle from http://homepage1.nifty.com/sabo10/rulelog/illust.html
solve: run {
  rowHint [0, 0 -> 3]
  rowHint [1, 0 -> 2 + 1 -> 2]
  rowHint [2, 0 -> 1 + 1 -> 1 + 2 -> 1]
  rowHint [3, 0 -> 3 + 1 -> 3]
  rowHint [4, 0 -> 5]
  rowHint [5, 0 -> 7]
  rowHint [6, 0 -> 7]
  rowHint [7, 0 -> 7]
  rowHint [8, 0 -> 7]
  rowHint [9, 0 -> 5]

  colHint [0, 0 -> 4]
  colHint [1, 0 -> 6]
  colHint [2, 0 -> 7]
  colHint [3, 0 -> 9]
  colHint [4, 0 -> 2 + 1 -> 7]
  colHint [5, 0 -> 1 + 1 -> 6]
  colHint [6, 0 -> 2 + 1 -> 4]
  colHint [7, 0 -> 3]
  colHint [8, 0 -> 1]
  colHint [9, 0 -> 2]
} for 10 but 5 Int

error: pathspec 'illust_logic/illustLogic.als' did not match any file(s) known to git


minor changes

minor changes

open module_featuremodel[Feature] as FeatureModel

abstract sig Feature {}

one sig Chassis extends Feature {}
one sig Wiper extends Feature {}
one sig StaticWagon extends Feature {}
one sig Cabriolet extends Feature {}
one sig ManualControl extends Feature {}
one sig RearWiper extends Feature {}
one sig FrontWiper extends Feature {}
one sig RoofControl extends Feature {}
one sig RainSensorWiper extends Feature {}
one sig IntervalWiper extends Feature {}
one sig AutoRoofControl extends Feature {}
one sig RainSensor extends Feature {}

pred init_feature_model {
	FeatureModel/Root[Chassis]

	FeatureModel/Mandatory[Chassis -> Wiper + Cabriolet -> RoofControl + RainSensorWiper -> RainSensor]
	FeatureModel/NoOptional
	FeatureModel/Alternative[Chassis -> (StaticWagon + Cabriolet) + FrontWiper -> (RainSensorWiper + IntervalWiper) + RoofControl -> (ManualControl + AutoRoofControl)]
	FeatureModel/OptionalOr[Wiper -> RearWiper]
	FeatureModel/MandatoryOr[Wiper -> FrontWiper]
	FeatureModel/Requires[StaticWagon -> RearWiper + AutoRoofControl -> RainSensor]
	FeatureModel/NoExcludes
}

run init_feature_model

error: pathspec 'eu.modelwriter.demonstration.alloyinecore/harun/example_featuremodel.als' did not match any file(s) known to git


Incomplete - task : Extend unit tests for complete coverage - updated model to clarify that non-sore losers are above the threshold

-- (c) 2010-2011, Dermot Cochran, IT University of Copenhagen
-- http://www.kindsoftware.com/about/people/dc
-- http://www.itu.dk/people/dero

module Voting

open util/integer

-- An individual person standing for election
sig Candidate {
    votes: 			  set Ballot, 	-- First preference ballots assigned to this candidate
	transfers: 	      set Ballot,   -- Ballots received by transfer from another candidate
	surplus: 		  set Ballot, 	-- Ballots given to another candidate (on election or elimination)
	outcome: 		  Event
} {
	no b: Ballot | b in votes & transfers
	all b: Ballot | b in votes + transfers implies this in b.assignees
	surplus in votes + transfers
	Election.method = Plurality implies #surplus = 0 and #transfers = 0
}

-- A digital or paper artifact which accurately records the intentions of the voter
sig Ballot {
  assignees: 		set Candidate,  -- Candidates to which this ballot has been assigned
  preferences: 	seq Candidate  -- Ranking of candidates
} {
	assignees in preferences.elems
    not preferences.hasDups
	preferences.elems in Election.candidates
	preferences.first in assignees
	Election.method = Plurality implies #preferences = 1
    0 < #preferences
}

-- An election result
one sig Scenario {
   	losers: 				set Candidate,
   	winners: 			set Candidate,
	eliminated: 		set Candidate, 		-- Candidates excluded under STV rules
	threshold: 		Int, 						-- Minimum number of votes for a Loser or EarlyLoser
	quota: 				Int						-- Minimum number of votes for a STV Winner or QuotaWinner
}
{
 	winners + losers = Election.candidates
 	#winners = Election.seats
 	no c: Candidate | c in losers & winners
 	0 < #losers
 	all w: Candidate | all l: Candidate | l in losers and w in winners implies
		((#l.votes + #l.transfers <= #w.votes + #w.transfers) and (#l.votes <= #w.votes))
	0 <= threshold
	threshold <= quota
    Election.method = STV implies (threshold = 1 + quota.div[4])
	Election.method = Plurality implies #eliminated = 0
	eliminated in losers
	all c: Candidate | c in losers implies Election.method = Plurality
       or #c.votes + #c.transfers < quota
}

/*
	There are four winner-outcomes and six loser-outcomes:

	Winner: 						(W1) elected in the first round of counting either by quota or plurality,
	QuotaWinner: 				(W2) elected with transfers from another candidate (STV only),
	CompromiseWinner: 	(W3) elected on the last round of counting without quota (STV only),
	TiedWinner:					(W4) elected by tie breaker,
	TiedLoser:					(L1) loses only by tie breaker but reaches the threshold,
	Loser:			 				(L2) defeated on last round but reaches the minimum threshold of votes,
    TiedEarlyLoser:			(L3) reaches threshold but eliminated by tie breaker (STV only),
	EarlyLoser:					(L4) reaches threshold but is eliminated before last round (STV only),
	TiedSoreLoser:				(L5) loses only by tie breaker but does not reach threshold,
	SoreLoser: 					(L6) does not even reach the mimimum threshold of votes
*/
enum Event {Winner, QuotaWinner, CompromiseWinner, TiedWinner,
	TiedLoser, Loser, TiedEarlyLoser, EarlyLoser, TiedSoreLoser, SoreLoser}

enum Method {Plurality, STV}

-- An Election Constituency
one sig Election {
  candidates: 	set Candidate,
  seats: 				Int,
  method: 			Method,
  ballots:			Int -- number of ballots cast
}
{
 	0 < seats
 	seats < #candidates
 	all c: Candidate | c in candidates
    ballots = #Ballot
    Scenario.quota = 1 + ballots.div[seats+1]
}

-- Independent (or Fundamental) Axioms
fact threshold {
   Election.method = Plurality implies Scenario.threshold = Election.ballots.div[20]
}

fact surplus {
  all c: Candidate | (c.outcome = Winner and Election.method = STV) implies
     Scenario.quota + #c.surplus = #c.votes
}

fact winnersWithoutTransfers {
  all c: Candidate | (c.outcome = Winner and Election.method = STV) implies #c.transfers = 0
}

fact surplusFromTransfers {
  all c: Candidate | c.outcome = QuotaWinner implies ((surplus in transfers) and
     ((Scenario.quota + #c.surplus) = (#c.votes + #c.transfers)))
}

fact integrity {
  all c: Candidate | all b: Ballot | b in c.votes implies c in b.assignees
}

fact pluralityEvents {
	all c: Candidate | Election.method = Plurality implies
		(c.outcome = Loser or c.outcome = SoreLoser or c.outcome = Winner or
		c.outcome = TiedWinner or c.outcome = TiedLoser)
}

fact winnerSTV {
	all c: Candidate | (Election.method = STV and c.outcome = Winner) implies
       Scenario.quota <= #c.votes
}

fact transferWinnerWithQuota {
	all c: Candidate | (Election.method = STV and c.outcome = QuotaWinner) implies
	   Scenario.quota <= #c.votes + #c.transfers
}

fact transferWinnerNotFirst {
	all c: Candidate |  (Election.method = STV and c.outcome = QuotaWinner) implies
		not Scenario.quota <= #c.votes
}

fact closeWinner {
	all c: Candidate | (c.outcome = CompromiseWinner or c.outcome = TiedWinner) implies
		not (Scenario.quota <= #c.votes + #c.transfers) or Election.method = Plurality
}

fact soreLoser {
	all c: Candidate | (c.outcome = SoreLoser or c.outcome = TiedSoreLoser) implies
		(#c.votes + #c.transfers < Scenario.threshold)
}

fact loser {
	all c: Candidate | (c.outcome = Loser or c.outcome = TiedLoser)
        implies (c in Scenario.losers and c not in Scenario.eliminated)
}

fact earlyLoser {
	all c: Candidate | (c.outcome = EarlyLoser or c.outcome = TiedEarlyLoser) iff
		(c in Scenario.eliminated and not (#c.votes + #c.transfers < Scenario.threshold))
}

fact winners {
	all c: Candidate | c in Scenario.winners iff
		(c.outcome = Winner or c.outcome = QuotaWinner or c.outcome = CompromiseWinner or
		c.outcome = TiedWinner)
}

fact losers {
	all c: Candidate | c in Scenario.losers iff
		(c.outcome = Loser or c.outcome = EarlyLoser or c.outcome = SoreLoser or
		c.outcome = TiedLoser or c.outcome = TiedEarlyLoser or c.outcome = TiedSoreLoser)
}

-- Non-Independent Axioms for Ballot Integrity
fact transfers {
	all c: Candidate | 0 < #c.transfers implies Election.method = STV
}

fact onlyWinnersAndQuotaWinnersHaveSurplus {
	all c: Candidate | 0 < #c.surplus implies
		(c.outcome = Winner or c.outcome = QuotaWinner)
}

fact winnersNeedNoTransfers {
		all c: Candidate | c.outcome = Winner implies 0 = #c.transfers
}

fact firstPreference {
	all b: Ballot | all c: Candidate | b.preferences.first = c iff b in c.votes
}

fact sizeOfSurplus {
	all c: Candidate | (c in Scenario.winners and Election.method = STV and 0 < #c.surplus) implies
		(#c.surplus = #c.votes + #c.transfers - Scenario.quota)
}

fact transferToNextPreference {
	all b: Ballot | all disj donor,receiver: Candidate |
		(donor + receiver in b.assignees and
		b in receiver.transfers and b in donor.surplus) implies
		(b.preferences.idxOf[donor] < b.preferences.idxOf[receiver] and
		receiver in b.preferences.rest.elems)
}

fact pluralityWinner {
	all disj a, b: Candidate | (Election.method = Plurality and Election.seats = 1 and
		a.outcome = Winner) implies #b.votes <= #a.votes
}

fact transferToNextContinuingCandidate {
	all disj skipped, receiving: Candidate | all b: Ballot |
		b.preferences.idxOf[skipped] < b.preferences.idxOf[receiving] and
		receiving in b.assignees and (not skipped in b.assignees) implies
		(skipped in Scenario.eliminated or skipped.outcome = Winner or
		skipped.outcome = QuotaWinner)
}

// All ballot transfers are associated with the last candidate to receive the transfer
fact ownership {
	all disj c,d: Candidate | all b: Ballot | b in c.transfers implies c in b.assignees and
		(d not in b.assignees or b.preferences.idxOf[d] < b.preferences.idxOf[c])
}

// Lowest candidate is eliminated first
fact lowestElimination {
	all disj c,d: Candidate | c in Scenario.eliminated and d not in Scenario.eliminated implies
		#c.votes + #c.transfers <= #d.votes + #d.transfers
}

// All ties involve equality between at least one winner and at least one loser on either original votes or
// on transfers plus original votes
fact equalityOfTiedWinner {
   all w: Candidate | some l: Candidate | w.outcome = TiedWinner and
	 	(l.outcome = TiedLoser or l.outcome = TiedSoreLoser or l.outcome = TiedEarlyLoser) implies
		(#l.votes = #w.votes) or (#l.votes + #l.transfers = #w.votes + #w.transfers)
}

fact equalityOfTiedLosers {
  all s: Candidate | some w: Candidate | w.outcome = TiedWinner and
       (s.outcome = SoreLoser or s.outcome = TiedLoser or s.outcome = TiedEarlyLoser) implies
       (#s.votes = #w.votes) or (#s.votes + #s.transfers = #w.votes + #w.transfers)
}

-- Scenario Validity Axioms
// When there is a tied sore loser then there are no non-sore losers
fact typeOfTiedLoser {
   no disj a,b: Candidate | a.outcome = TiedSoreLoser and
        (b.outcome = TiedLoser or b.outcome = TiedEarlyLoser or
         b.outcome=Loser or b.outcome=EarlyLoser)
}

fact tieBreaker {
	all w: Candidate | some l: Candidate | w.outcome = TiedWinner implies
		(l.outcome = TiedLoser or l.outcome = TiedSoreLoser or l.outcome = TiedEarlyLoser)
}

fact validTieBreaker {
	all l: Candidate | some w: Candidate |
    (l.outcome = TiedLoser or l.outcome = TiedSoreLoser or l.outcome = TiedEarlyLoser) implies
    w.outcome = TiedWinner and 0 < #w.votes + #w.transfers
}

// Compromise winner must have more votes than any tied winners
fact compromiseNotTied {
	all disj c,t: Candidate | (c.outcome = CompromiseWinner and t.outcome = TiedWinner) implies
		#t.votes + #t.transfers < #c.votes + #c.transfers
}

// Equal losers are tied
fact equalityofTiedWinnersAndLosers {
	all disj w,l: Candidate | w in Scenario.winners and l in Scenario.losers and
		#w.votes = #l.votes and #w.transfers = #l.transfers implies
			w.outcome = TiedWinner and 0 < #w.votes + #w.transfers and
			(l.outcome = TiedLoser or l.outcome = TiedEarlyLoser or l.outcome = TiedSoreLoser)
}

// Highest winner has a quota
fact highestWinners {
   all c: Candidate | Election.method = STV and c.outcome = Winner implies
		Scenario.quota <= #c.votes + #c.transfers
}

// Tied Winners and Tied Losers have an equal number of votes
fact equalTies {
	all disj a,b: Candidate | a.outcome = TiedWinner and b.outcome = TiedLoser implies
		#a.votes = #b.votes and #a.transfers = #b.transfers
}

// Winners have more votes than non-tied losers
fact winnersHaveVotes {
	all w,l: Candidate | w.outcome = Winner and
      (l.outcome = Loser or l.outcome = EarlyLoser or l.outcome = SoreLoser) implies
     ((#l.votes < #w.votes) or (#l.votes + #l.transfers < #w.votes + #w.transfers))
}

// All non-sore losers are above the threshold
fact losersAboveThreshold {
  all c: Candidate | c.outcome = Loser implies (Scenario.threshold < #c.votes + #c.transfers)
}

fact earlyLosersAboveThreshold {
  all c: Candidate | c.outcome = EarlyLoser implies (Scenario.threshold < #c.votes + #c.transfers)
}

fact tiedLosersAboveThreshold {
  all c: Candidate | c.outcome = TiedLoser implies (Scenario.threshold < #c.votes + #c.transfers)
}

fact tiedEarlyLosersAboveThreshold {
  all c: Candidate | c.outcome = TiedEarlyLoser implies (Scenario.threshold < #c.votes + #c.transfers)
}

-- Basic Lemmas
assert honestCount {
	  all c: Candidate | all b: Ballot | b in c.votes + c.transfers implies c in b.assignees
}
check honestCount for 15 but 6 int

assert atLeastOneLoser {
	0 < #Scenario.losers
}
check atLeastOneLoser for 15 but 6 int

assert atLeastOneWinner {
	0 < #Scenario.winners
}
check atLeastOneWinner for 14 but 6 int

assert plurality {
	all c: Candidate | all b: Ballot | b in c.votes and
		Election.method = Plurality implies c in b.preferences.first
}
check plurality for 18 but 6 int

assert wellFormedTieBreaker {
	some w,l : Candidate | (w in Scenario.winners and l in Scenario.losers and
		#w.votes = #l.votes and #w.transfers = #l.transfers) implies
		w.outcome = TiedWinner and
		(l.outcome = TiedLoser or l.outcome = TiedSoreLoser or l.outcome=TiedEarlyLoser)
}
check wellFormedTieBreaker for 18 but 6 int

assert validSurplus {
	all c: Candidate | 0 < #c.surplus implies (c.outcome = Winner or c.outcome = QuotaWinner or
		c in Scenario.eliminated)
}
check validSurplus for 16 but 6 int

-- Advanced Lemmas
// No lost votes during counting
assert accounting {
	all b: Ballot | some c: Candidate | b in c.votes and c in b.assignees
}
check accounting for 16 but 6 int

// Cannot have tie breaker with both tied sore loser and non-sore loser
assert tiedWinnerLoserTiedSoreLoser {
	no disj c,w,l: Candidate | c.outcome = TiedSoreLoser and
	   w.outcome = TiedWinner and (l.outcome = Loser or l.outcome = TiedLoser)
}
check tiedWinnerLoserTiedSoreLoser for 6 int

// Compromise winner must have at least one vote
assert validCompromise {
	all c: Candidate | c.outcome = CompromiseWinner implies 0 < #c.votes + #c.transfers
}
check validCompromise for 6 int

// Quota not more than the number of ballots cast
assert maxQuota {
  Scenario.quota <= #Ballot
}
check maxQuota for 7 int

// Quota winner needs transfers
assert quotaWinnerNeedsTransfers {
  all c: Candidate | c.outcome = QuotaWinner implies 0 < #c.transfers
}
check quotaWinnerNeedsTransfers for 7 int

// Sore losers below threshold
assert soreLoserBelowThreshold {
  all c: Candidate | c.outcome = SoreLoser implies not (Scenario.threshold <= #c.votes + #c.transfers)
}
check soreLoserBelowThreshold for 10 but 6 int

// Possible outcomes when under the threshold
assert underThresholdOutcomes {
  all c: Candidate | (#c.votes + #c.transfers < Scenario.threshold) implies
     (c.outcome = SoreLoser or c.outcome = TiedSoreLoser or c.outcome = TiedWinner or
     c.outcome = CompromiseWinner)
}
check underThresholdOutcomes for 10 but 6 int

-- Sample scenarios
pred TwoCandidatePlurality {
	Election.method = Plurality
	Election.seats = 1
	#Election.candidates = 2
}
run TwoCandidatePlurality for 10 but 2 Ballot, 6 int

pred PluralityTiedWinner {
	Election.method = Plurality
	Election.seats = 1
	some disj a,b: Candidate | a.outcome = TiedWinner and b.outcome = TiedLoser
}
run PluralityTiedWinner for 10 but 2 Ballot, 6 int

pred ThreeCandidatePlurality {
	Election.method = Plurality
	Election.seats = 1
	#Election.candidates = 3
}
run ThreeCandidatePlurality for 6 int

pred Plurality {
	Election.method = Plurality
	Election.seats = 1
	3 < #Election.candidates
}
run Plurality for 5 but 6 int

pred TenCandidatePluralityWithTwoSeats {
	Election.method = Plurality
	Election.seats = 2
	#Election.candidates = 10
}
run TenCandidatePluralityWithTwoSeats for 10 but 6 int

pred InstantRunoffVoting {
	Election.method = STV
	Election.seats = 1
	3 < #Election.candidates
}
run InstantRunoffVoting for 10 but 6 int

pred STV3 {
	Election.method = STV
	Election.seats = 3
}
run STV3 for 5 but 6 int

pred ThreeWinnersOneLoser {
    Election.method = STV
	some disj a,b,d: Candidate | a.outcome = Winner
   	  and b.outcome = QuotaWinner or b.outcome = CompromiseWinner
	  and d in Scenario.losers
}
run ThreeWinnersOneLoser for 6 but 6 int

pred LoserAndEarlyLoser {
	one d: Candidate | d.outcome = Loser
	one e: Candidate | e.outcome = EarlyLoser
}
run LoserAndEarlyLoser for 5 but 6 int

pred OneWinnerNineLosers {
	#Scenario.winners = 1
	#Scenario.losers = 9
}
run OneWinnerNineLosers for 16 but 6 int

pred ThreeWayTie {
	#Election.candidates = 3
    Election.method = Plurality
	some disj a,b,c: Candidate | a.outcome = TiedWinner and
		b.outcome = TiedLoser and
		c.outcome = TiedLoser
}
run ThreeWayTie for 5 but 6 int

pred FiveWayTie {
	some disj a,b,c,d,e: Candidate | a.outcome = TiedWinner and
	    b.outcome = TiedLoser and
		c.outcome = TiedLoser and d.outcome = TiedLoser and e.outcome = TiedWinner
}
run FiveWayTie for 7 but 6 int

pred ScenarioLWW {
	some disj a,b,c: Candidate | a.outcome = Loser and b.outcome = Winner and
		c.outcome = Winner
    #Election.candidates = 3
	Election.method = STV
    0 < #Ballot
}
run ScenarioLWW for 7 but 7 int

pred LongBallot {
	some b: Ballot | #b.preferences = 7
}
run LongBallot for 7 but 6 int

pred MultipleBallotsUnderSTV {
	Election.method = STV
	some disj a,b,c,d: Ballot | 1 < #a.preferences and 1 < #b.preferences
	and 0 < #c.preferences and 0 < #d.preferences and
        a.preferences.first = b.preferences.last
}
run MultipleBallotsUnderSTV for 10 but 6 int

pred WinnerLoserEarlyLoser {
	some a,b,c,d : Candidate | a.outcome = Winner and b.outcome = Loser and
		c.outcome = EarlyLoser and d.outcome = SoreLoser
	Election.method = STV
}
run WinnerLoserEarlyLoser for 7 but 6 int

pred TiedScenario {
  some disj a,b: Candidate | a.outcome = TiedLoser and b.outcome = TiedWinner
     Election.method = STV
     #Election.candidates = 2
     #Election.seats = 1
}
run TiedScenario for 7 but 6 int

pred NoTiesAndNoSoresScenarios {
  Election.method = STV
  #Election.candidates > 3
  #Ballot > 6
  no c: Candidate | c.outcome = TiedLoser or c.outcome = TiedWinner or
    c.outcome = TiedEarlyLoser or c.outcome = TiedSoreLoser or c.outcome = SoreLoser
}
run NoTiesAndNoSoresScenarios for 10 but 6 int

-- Scenario tests
pred LW {
  some disj c0,c1: Candidate | c0.outcome = Winner and c1.outcome = Loser and
	Election.method = STV and #Election.candidates = 2 and #Election.seats = 1 and
    (Scenario.threshold < #c1.votes + #c1.transfers)
}
run LW for 10 but 6 int

pred LQ {
	some disj a,b: Candidate | a.outcome = Loser and b.outcome = QuotaWinner
    #Election.candidates = 2
	Election.method = STV
    0 < #Ballot
}
run LQ for 10 but 6 int

pred LQQ {
	some disj a,b,c: Candidate | a.outcome = Loser and b.outcome = QuotaWinner and
       c.outcome = QuotaWinner
    #Election.candidates = 3
	Election.method = STV
    0 < #Ballot
}
run LQQ for 10 but 6 int

pred LQW {
	some disj a,b,c: Candidate | a.outcome = Loser and b.outcome = QuotaWinner and
		c.outcome = Winner
    #Election.candidates = 3
	Election.method = STV
    0 < #Ballot
}
run LQW for 10 but 6 int

pred LQQW {
	some disj a,b,c,d: Candidate | a.outcome = Loser and b.outcome = QuotaWinner and
		c.outcome = Winner and d.outcome = QuotaWinner
    #Election.candidates = 4
	Election.method = STV
    0 < #Ballot
}
run LQQW for 10 but 6 int

pred SLQQW {
	some disj a,b,c,d,e: Candidate | a.outcome = Loser and b.outcome = QuotaWinner and
		c.outcome = Winner and d.outcome = QuotaWinner and e.outcome = SoreLoser
    #Election.candidates = 5
	Election.method = STV
    0 < #Ballot
}
run SLQQW for 10 but 6 int

-- Version Control for changes to model
one sig Version {
   year, month, day : Int
} {
  year = 11
  month = 01
  day = 18
  -- Dermot Cochran 2011-01-18
}

-- (c) 2010-2011, Dermot Cochran, IT University of Copenhagen
-- http://www.kindsoftware.com/about/people/dc
-- http://www.itu.dk/people/dero

module Voting

open util/integer

-- An individual person standing for election
sig Candidate {
    votes: 			  set Ballot, 	-- First preference ballots assigned to this candidate
	transfers: 	      set Ballot,   -- Ballots received by transfer from another candidate
	surplus: 		  set Ballot, 	-- Ballots given to another candidate (on election or elimination)
	outcome: 		  Event
} {
	no b: Ballot | b in votes & transfers
	all b: Ballot | b in votes + transfers implies this in b.assignees
	surplus in votes + transfers
	Election.method = Plurality implies #surplus = 0 and #transfers = 0
}

-- A digital or paper artifact which accurately records the intentions of the voter
sig Ballot {
  assignees: 		set Candidate,  -- Candidates to which this ballot has been assigned
  preferences: 	seq Candidate  -- Ranking of candidates
} {
	assignees in preferences.elems
    not preferences.hasDups
	preferences.elems in Election.candidates
	preferences.first in assignees
	Election.method = Plurality implies #preferences = 1
    0 < #preferences
}

-- An election result
one sig Scenario {
   	losers: 				set Candidate,
   	winners: 			set Candidate,
	eliminated: 		set Candidate, 		-- Candidates excluded under STV rules
	threshold: 		Int, 						-- Minimum number of votes for a Loser or EarlyLoser
	quota: 				Int						-- Minimum number of votes for a STV Winner or QuotaWinner
}
{
 	winners + losers = Election.candidates
 	#winners = Election.seats
 	no c: Candidate | c in losers & winners
 	0 < #losers
 	all w: Candidate | all l: Candidate | l in losers and w in winners implies
		((#l.votes + #l.transfers <= #w.votes + #w.transfers) and (#l.votes <= #w.votes))
	0 <= threshold
	threshold <= quota
    Election.method = STV implies (threshold = 1 + quota.div[4])
	Election.method = Plurality implies #eliminated = 0
	eliminated in losers
	all c: Candidate | c in losers implies Election.method = Plurality
       or #c.votes + #c.transfers < quota
}

/*
	There are four winner-outcomes and six loser-outcomes:

	Winner: 						(W1) elected in the first round of counting either by quota or plurality,
	QuotaWinner: 				(W2) elected with transfers from another candidate (STV only),
	CompromiseWinner: 	(W3) elected on the last round of counting without quota (STV only),
	TiedWinner:					(W4) elected by tie breaker,
	TiedLoser:					(L1) loses only by tie breaker but reaches the threshold,
	Loser:			 				(L2) defeated on last round but reaches the minimum threshold of votes,
    TiedEarlyLoser:			(L3) reaches threshold but eliminated by tie breaker (STV only),
	EarlyLoser:					(L4) reaches threshold but is eliminated before last round (STV only),
	TiedSoreLoser:				(L5) loses only by tie breaker but does not reach threshold,
	SoreLoser: 					(L6) does not even reach the mimimum threshold of votes
*/
enum Event {Winner, QuotaWinner, CompromiseWinner, TiedWinner,
	TiedLoser, Loser, TiedEarlyLoser, EarlyLoser, TiedSoreLoser, SoreLoser}

enum Method {Plurality, STV}

-- An Election Constituency
one sig Election {
  candidates: 	set Candidate,
  seats: 				Int,
  method: 			Method,
  ballots:			Int -- number of ballots cast
}
{
 	0 < seats
 	seats < #candidates
 	all c: Candidate | c in candidates
    ballots = #Ballot
    Scenario.quota = 1 + ballots.div[seats+1]
}

-- Independent (or Fundamental) Axioms
fact threshold {
   Election.method = Plurality implies Scenario.threshold = Election.ballots.div[20]
}

fact surplus {
  all c: Candidate | (c.outcome = Winner and Election.method = STV) implies
     Scenario.quota + #c.surplus = #c.votes
}

fact winnersWithoutTransfers {
  all c: Candidate | (c.outcome = Winner and Election.method = STV) implies #c.transfers = 0
}

fact surplusFromTransfers {
  all c: Candidate | c.outcome = QuotaWinner implies ((surplus in transfers) and
     ((Scenario.quota + #c.surplus) = (#c.votes + #c.transfers)))
}

fact integrity {
  all c: Candidate | all b: Ballot | b in c.votes implies c in b.assignees
}

fact pluralityEvents {
	all c: Candidate | Election.method = Plurality implies
		(c.outcome = Loser or c.outcome = SoreLoser or c.outcome = Winner or
		c.outcome = TiedWinner or c.outcome = TiedLoser)
}

fact winnerSTV {
	all c: Candidate | (Election.method = STV and c.outcome = Winner) implies
       Scenario.quota <= #c.votes
}

fact transferWinnerWithQuota {
	all c: Candidate | (Election.method = STV and c.outcome = QuotaWinner) implies
	   Scenario.quota <= #c.votes + #c.transfers
}

fact transferWinnerNotFirst {
	all c: Candidate |  (Election.method = STV and c.outcome = QuotaWinner) implies
		not Scenario.quota <= #c.votes
}

fact closeWinner {
	all c: Candidate | (c.outcome = CompromiseWinner or c.outcome = TiedWinner) implies
		not (Scenario.quota <= #c.votes + #c.transfers) or Election.method = Plurality
}

fact soreLoser {
	all c: Candidate | (c.outcome = SoreLoser or c.outcome = TiedSoreLoser) implies
		(#c.votes + #c.transfers < Scenario.threshold)
}

fact loser {
	all c: Candidate | (c.outcome = Loser or c.outcome = TiedLoser or c.outcome = TiedSoreLoser)
        implies c in Scenario.losers - Scenario.eliminated
}

fact earlyLoser {
	all c: Candidate | (c.outcome = EarlyLoser or c.outcome = TiedEarlyLoser) iff
		(c in Scenario.losers & Scenario.eliminated and not #c.votes + #c.transfers < Scenario.threshold)
}

fact winners {
	all c: Candidate | c in Scenario.winners iff
		(c.outcome = Winner or c.outcome = QuotaWinner or c.outcome = CompromiseWinner or
		c.outcome = TiedWinner)
}

fact losers {
	all c: Candidate | c in Scenario.losers iff
		(c.outcome = Loser or c.outcome = EarlyLoser or c.outcome = SoreLoser or
		c.outcome = TiedLoser or c.outcome = TiedEarlyLoser or c.outcome = TiedSoreLoser)
}

-- Non-Independent Axioms for Ballot Integrity
fact transfers {
	all c: Candidate | 0 < #c.transfers implies Election.method = STV
}

fact onlyWinnersAndQuotaWinnersHaveSurplus {
	all c: Candidate | 0 < #c.surplus implies
		c.outcome = Winner or c.outcome = QuotaWinner
}

fact winnersNeedNoTransfers {
		all c: Candidate | c.outcome = Winner implies 0 = #c.transfers
}

fact firstPreference {
	all b: Ballot | all c: Candidate | b.preferences.first = c iff b in c.votes
}

fact sizeOfSurplus {
	all c: Candidate | (c in Scenario.winners and Election.method = STV and 0 < #c.surplus) implies
		#c.surplus = #c.votes + #c.transfers - Scenario.quota
}

fact transferToNextPreference {
	all b: Ballot | all disj donor,receiver: Candidate |
		(donor + receiver in b.assignees and
		b in receiver.transfers and b in donor.surplus implies
		b.preferences.idxOf[donor] < b.preferences.idxOf[receiver] and
		receiver in b.preferences.rest.elems)
}

fact pluralityWinner {
	all disj a, b: Candidate | (Election.method = Plurality and Election.seats = 1) and
		a.outcome = Winner implies #b.votes <= #a.votes
}

fact transferToNextContinuingCandidate {
	all disj skipped, receiving: Candidate | all b: Ballot |
		b.preferences.idxOf[skipped] < b.preferences.idxOf[receiving] and
		receiving in b.assignees and (not skipped in b.assignees) implies
		(skipped in Scenario.eliminated or skipped.outcome = Winner or
		skipped.outcome = QuotaWinner)
}

// All ballots transfers are associated with the last candidate to receive the transfer
fact ownership {
	all disj c,d: Candidate | all b: Ballot | b in c.transfers implies c in b.assignees and
		(d not in b.assignees or b.preferences.idxOf[d] < b.preferences.idxOf[c])
}

// Lowest candidate is eliminated first
fact lowestElimination {
	all disj c,d: Candidate | c in Scenario.eliminated and d not in Scenario.eliminated implies
		#c.votes + #c.transfers <= #d.votes + #d.transfers
}

// All ties involve equality between at least one winner and at least one loser on either original votes or
// on transfers plus original votes
fact equalityOfTiedWinner {
   all w: Candidate | some l: Candidate | w.outcome = TiedWinner and
	 	(l.outcome = TiedLoser or l.outcome = TiedSoreLoser or l.outcome = TiedEarlyLoser) implies
		(#l.votes = #w.votes) or (#l.votes + #l.transfers = #w.votes + #w.transfers)
}

fact equalityOfTiedLosers {
  all s: Candidate | some w: Candidate | w.outcome = TiedWinner and
       (s.outcome = SoreLoser or s.outcome = TiedLoser or s.outcome = TiedEarlyLoser) implies
       (#s.votes = #w.votes) or (#s.votes + #s.transfers = #w.votes + #w.transfers)
}

-- Scenario Validity Axioms
// When there is a tied sore loser then there are no non-sore losers
fact typeOfTiedLoser {
   no disj a,b: Candidate | a.outcome = TiedSoreLoser and
        (b.outcome = TiedLoser or b.outcome = TiedEarlyLoser or
         b.outcome=Loser or b.outcome=EarlyLoser)
}

fact tieBreaker {
	all w: Candidate | some l: Candidate | w.outcome = TiedWinner implies
		(l.outcome = TiedLoser or l.outcome = TiedSoreLoser or l.outcome = TiedEarlyLoser)
}

fact validTieBreaker {
	all l: Candidate | some w: Candidate |
    (l.outcome = TiedLoser or l.outcome = TiedSoreLoser or l.outcome = TiedEarlyLoser) implies
    w.outcome = TiedWinner and 0 < #w.votes + #w.transfers
}

// Compromise winner must have more votes than any tied winners
fact compromiseNotTied {
	all disj c,t: Candidate | (c.outcome = CompromiseWinner and t.outcome = TiedWinner) implies
		#t.votes + #t.transfers < #c.votes + #c.transfers
}

// Equal losers are tied
fact equalityofTiedWinnersAndLosers {
	all disj w,l: Candidate | w in Scenario.winners and l in Scenario.losers and
		#w.votes = #l.votes and #w.transfers = #l.transfers implies
			w.outcome = TiedWinner and 0 < #w.votes + #w.transfers and
			(l.outcome = TiedLoser or l.outcome = TiedEarlyLoser or l.outcome = TiedSoreLoser)
}

// Highest winner has a quota
fact highestWinners {
   all c: Candidate | Election.method = STV and c.outcome = Winner implies
		Scenario.quota <= #c.votes + #c.transfers
}

// Tied Winners and Tied Losers have an equal number of votes
fact equalTies {
	all disj a,b: Candidate | a.outcome = TiedWinner and b.outcome = TiedLoser implies
		#a.votes = #b.votes and #a.transfers = #b.transfers
}

// Winners have more votes than non-tied losers
fact winnersHaveVotes {
	all w,l: Candidate | w.outcome = Winner and
      (l.outcome = Loser or l.outcome = EarlyLoser or l.outcome = SoreLoser) implies
     ((#l.votes < #w.votes) or (#l.votes + #l.transfers < #w.votes + #w.transfers))
}

// Losers above threshold
fact losersAboveThreshold {
  all c: Candidate | c.outcome = Loser implies Scenario.threshold < (#c.votes + #c.transfers)
}

-- Basic Lemmas
assert honestCount {
	  all c: Candidate | all b: Ballot | b in c.votes + c.transfers implies c in b.assignees
}
check honestCount for 15 but 6 int

assert atLeastOneLoser {
	0 < #Scenario.losers
}
check atLeastOneLoser for 15 but 6 int

assert atLeastOneWinner {
	0 < #Scenario.winners
}
check atLeastOneWinner for 14 but 6 int

assert plurality {
	all c: Candidate | all b: Ballot | b in c.votes and
		Election.method = Plurality implies c in b.preferences.first
}
check plurality for 18 but 6 int

assert wellFormedTieBreaker {
	some w,l : Candidate | (w in Scenario.winners and l in Scenario.losers and
		#w.votes = #l.votes and #w.transfers = #l.transfers) implies
		w.outcome = TiedWinner and
		(l.outcome = TiedLoser or l.outcome = TiedSoreLoser or l.outcome=TiedEarlyLoser)
}
check wellFormedTieBreaker for 18 but 6 int

assert validSurplus {
	all c: Candidate | 0 < #c.surplus implies (c.outcome = Winner or c.outcome = QuotaWinner or
		c in Scenario.eliminated)
}
check validSurplus for 16 but 6 int

-- Advanced Lemmas
// No lost votes during counting
assert accounting {
	all b: Ballot | some c: Candidate | b in c.votes and c in b.assignees
}
check accounting for 16 but 6 int

// Cannot have tie breaker with both tied sore loser and non-sore loser
assert tiedWinnerLoserTiedSoreLoser {
	no disj c,w,l: Candidate | c.outcome = TiedSoreLoser and
	   w.outcome = TiedWinner and (l.outcome = Loser or l.outcome = TiedLoser)
}
check tiedWinnerLoserTiedSoreLoser for 6 int

// Compromise winner must have at least one vote
assert validCompromise {
	all c: Candidate | c.outcome = CompromiseWinner implies 0 < #c.votes + #c.transfers
}
check validCompromise for 6 int

// Quota not more than the number of ballots cast
assert maxQuota {
  Scenario.quota <= #Ballot
}
check maxQuota for 7 int

// Quota winner needs transfers
assert quotaWinnerNeedsTransfers {
  all c: Candidate | c.outcome = QuotaWinner implies 0 < #c.transfers
}
check quotaWinnerNeedsTransfers for 7 int

-- Sample scenarios
pred TwoCandidatePlurality {
	Election.method = Plurality
	Election.seats = 1
	#Election.candidates = 2
}
run TwoCandidatePlurality for 10 but 2 Ballot, 6 int

pred PluralityTiedWinner {
	Election.method = Plurality
	Election.seats = 1
	some disj a,b: Candidate | a.outcome = TiedWinner and b.outcome = TiedLoser
}
run PluralityTiedWinner for 10 but 2 Ballot, 6 int

pred ThreeCandidatePlurality {
	Election.method = Plurality
	Election.seats = 1
	#Election.candidates = 3
}
run ThreeCandidatePlurality for 6 int

pred Plurality {
	Election.method = Plurality
	Election.seats = 1
	3 < #Election.candidates
}
run Plurality for 5 but 6 int

pred TenCandidatePluralityWithTwoSeats {
	Election.method = Plurality
	Election.seats = 2
	#Election.candidates = 10
}
run TenCandidatePluralityWithTwoSeats for 10 but 6 int

pred InstantRunoffVoting {
	Election.method = STV
	Election.seats = 1
	3 < #Election.candidates
}
run InstantRunoffVoting for 10 but 6 int

pred STV3 {
	Election.method = STV
	Election.seats = 3
}
run STV3 for 5 but 6 int

pred ThreeWinnersOneLoser {
    Election.method = STV
	some disj a,b,d: Candidate | a.outcome = Winner
   	  and b.outcome = QuotaWinner or b.outcome = CompromiseWinner
	  and d in Scenario.losers
}
run ThreeWinnersOneLoser for 6 but 6 int

pred LoserAndEarlyLoser {
	one d: Candidate | d.outcome = Loser
	one e: Candidate | e.outcome = EarlyLoser
}
run LoserAndEarlyLoser for 5 but 6 int

pred OneWinnerNineLosers {
	#Scenario.winners = 1
	#Scenario.losers = 9
}
run OneWinnerNineLosers for 16 but 6 int

pred ThreeWayTie {
	#Election.candidates = 3
    Election.method = Plurality
	some disj a,b,c: Candidate | a.outcome = TiedWinner and
		b.outcome = TiedLoser and
		c.outcome = TiedLoser
}
run ThreeWayTie for 5 but 6 int

pred FiveWayTie {
	some disj a,b,c,d,e: Candidate | a.outcome = TiedWinner and
	    b.outcome = TiedLoser and
		c.outcome = TiedLoser and d.outcome = TiedLoser and e.outcome = TiedWinner
}
run FiveWayTie for 7 but 6 int

pred ScenarioLWW {
	some disj a,b,c: Candidate | a.outcome = Loser and b.outcome = Winner and
		c.outcome = Winner
    #Election.candidates = 3
	Election.method = STV
    0 < #Ballot
}
run ScenarioLWW for 7 but 7 int

pred LongBallot {
	some b: Ballot | #b.preferences = 7
}
run LongBallot for 7 but 6 int

pred MultipleBallotsUnderSTV {
	Election.method = STV
	some disj a,b,c,d: Ballot | 1 < #a.preferences and 1 < #b.preferences
	and 0 < #c.preferences and 0 < #d.preferences and
        a.preferences.first = b.preferences.last
}
run MultipleBallotsUnderSTV for 10 but 6 int

pred WinnerLoserEarlyLoser {
	some a,b,c,d : Candidate | a.outcome = Winner and b.outcome = Loser and
		c.outcome = EarlyLoser and d.outcome = SoreLoser
	Election.method = STV
}
run WinnerLoserEarlyLoser for 7 but 6 int

pred TiedScenario {
  some disj a,b: Candidate | a.outcome = TiedLoser and b.outcome = TiedWinner
     Election.method = STV
     #Election.candidates = 2
     #Election.seats = 1
}
run TiedScenario for 7 but 6 int

pred NoTiesAndNoSoresScenarios {
  Election.method = STV
  #Election.candidates > 3
  #Ballot > 6
  no c: Candidate | c.outcome = TiedLoser or c.outcome = TiedWinner or
    c.outcome = TiedEarlyLoser or c.outcome = TiedSoreLoser or c.outcome = SoreLoser
}
run NoTiesAndNoSoresScenarios for 10 but 6 int

-- Scenario tests
pred LW {
  some disj c0,c1: Candidate | c0.outcome = Winner and c1.outcome = Loser and
	Election.method = STV and #Election.candidates = 2 and #Election.seats = 1
}
run LW for 10 but 6 int

pred LQ {
	some disj a,b: Candidate | a.outcome = Loser and b.outcome = QuotaWinner
    #Election.candidates = 2
	Election.method = STV
    0 < #Ballot
}
run LQ for 10 but 6 int

pred LQQ {
	some disj a,b,c: Candidate | a.outcome = Loser and b.outcome = QuotaWinner and
       c.outcome = QuotaWinner
    #Election.candidates = 3
	Election.method = STV
    0 < #Ballot
}
run LQQ for 10 but 6 int

pred LQW {
	some disj a,b,c: Candidate | a.outcome = Loser and b.outcome = QuotaWinner and
		c.outcome = Winner
    #Election.candidates = 3
	Election.method = STV
    0 < #Ballot
}
run LQW for 10 but 6 int

pred LQQW {
	some disj a,b,c,d: Candidate | a.outcome = Loser and b.outcome = QuotaWinner and
		c.outcome = Winner and d.outcome = QuotaWinner
    #Election.candidates = 4
	Election.method = STV
    0 < #Ballot
}
run LQQW for 10 but 6 int

-- Version Control for changes to signatures and axioms, excluding lemmas and predicates
one sig Version {
   year, month, day : Int
} {
  year = 11
  month = 01
  day = 17
  -- Dermot Cochran 2011-01-17
}


Removed old code

Removed old code

// Relational version of history

module histRelat
open c11Relat

pred preexecWF [ dom : set Action, kind : Action -> Kind,
                 gloc, lloc : Action -> Loc, sb : Action -> Action ] {
  // no kind.RMW

  SBwf[dom, kind, sb]
  locWF[dom, kind, gloc, lloc]

  // External actions are unordered in sb
  no sb & ((Extern -> Action) + (Action -> Extern))

  // Internal actions are totally ordered in sb
  all disj a1, a2 : (dom & Intern) |
    a1 -> a2 in (^sb + ^(~sb))

  // Call / Return bracket internal actions
  all c : dom & Call, r : dom & Ret | {
    (c -> r) in ^sb
    all i : dom |
      i in Intern iff (c -> i) + (i -> r) in ^sb
  }
}

fun HBvsMO_d [ dom : set Action, kind : Action -> Kind,
               loc : Action -> Loc, wv, rv : Action -> Val,
               hb, sb, mo, rf : Action -> Action ]
                  : (Action -> Action) {
  { u : (Extern + Ret), v : (Extern + Call) |
    some disj w1, w2 : (dom <: loc.Atomic) |
    {
      (w2 -> w1) in mo
      (w1 -> u) + (v -> w2) in (iden + hb)
    }
  }
}

fun CoWR_d [ dom : set Action, kind : Action -> Kind,
             loc : Action -> Loc, wv, rv : Action -> Val,
             hb, sb, mo, rf : Action -> Action ]
                : (Action -> Action) {
  { u : (Extern + Ret), v : (Extern + Call) |
    disj [u,v] and
    some w1, w2 : kind.Write & (dom <: loc.Atomic),
               r : kind.Read & (dom <: loc.Atomic)   |
    {
      disj [w1, w2, r]
      (w1 -> r) in rf
      (w1 -> w2) in mo
      (w2 -> u) in iden + hb
      (v -> r) in iden + hb
    }
  }
}

fun HBacyc_d [ dom : set Action, kind : Action -> Kind,
               loc : Action -> Loc, wv, rv : Action -> Val,
               hb, sb, mo, rf : Action -> Action ]
                 : (Action -> Action) {
  { u : (Extern + Ret), v : (Extern + Call) |
    disj [u,v]
   and
    (v -> u) in hb
  }
}

fun getguar[ dom : Action, hb : Action -> Action ] : Action -> Action {
  hb & ((Extern -> Extern) + (Call -> Extern) +  (Extern -> Ret))
}

fun getdeny[ dom : set Action, kind : Action -> Kind,
             loc : Action -> Loc, wv, rv : Action -> Val,
             hb, sb, mo, rf : Action -> Action ]
                 : Action -> Action {
   // Note: removed Ret -> Call deny because it's already enforced by sb
   (CoWR_d[dom, kind, loc, wv, rv, ^hb, sb, mo, rf]
     +
    HBvsMO_d[dom, kind, loc, wv, rv, ^hb, sb, mo, rf]
     +
    HBacyc_d[dom, kind, loc, wv, rv, ^hb, sb, mo, rf])
        - (Ret -> Call)
}

/*************************************************/
/* Cutting Predicates                            */
/*************************************************/

pred cutR[ dom : set Action, kind : Action -> Kind,
           loc : Action -> Loc, wv, rv : Action -> Val,
           hb, sb, mo, rf : Action -> Action ] {
  all r : Extern & kind.Read & loc.Atomic & dom |
  some w : Intern & dom | {
    (w -> r) in rf
    no (w.rf & Extern) - r
  }
}

fun vizAct[ dom : set Action, rf : Action -> Action ] : Action  {
  // Internal actions
  (dom & Intern) +
  // External actions that are read or read from internal actions
  { a : dom & Extern |
    some a' : dom & Intern | some ((a -> a') + (a' -> a)) & rf }
}

pred cutW[ dom : set Action, kind : Action -> Kind,
            loc : Action -> Loc, wv, rv : Action -> Val,
            hb, sb, mo, rf : Action -> Action ] {
  all disj w, w' : Extern & dom | {
    {(w.loc = w'.loc) and (no (w + w') & vizAct[dom, rf])}
       implies
    some w'' : vizAct[dom, rf] |
       (w -> w'') + (w'' -> w') in mo
  }
}

//fun getinterf[ dom : set Action ] : set Action {
//  dom & (Extern + Call + Ret)
//}

// // run hist_run_simp
// //   { some dom : set Action, hb, sb, mo, rf : Action -> Action | {
// //      valid[dom, ^hb, sb, mo, rf]
// //      // DRF[dom, ^hb, sb, mo, rf]
// //
// //      // Sanity conditions
// //      dom = Action
// //      Loc = dom.loc
// //      is_core[hb]
// //      is_core[sb]
// //      //some Extern & Write
// //      //some Intern.loc & (Extern & Write).loc
// //
// //      some disj w0, w1, w2 : Write | {
// //        w0 + w1 in Intern
// //        w2 in Extern
// //        one w0.loc + w1.loc + w2.loc
// //        w0.loc in Atomic
// //      }
// //
// //      one Call
// //      one Ret
// //      preexecWF[ dom, sb ]
// //
// //      interesting_exec[dom, ^hb, sb, mo, rf]
// //
// //      some l : Glob & Atomic, v : Val | write2[ dom - Extern, sb, l, v]
// //   }
// // } for 5

/*************************************************/
/* Tests                                         */
/*************************************************/

// run hist_run
//   { some dom : set Action, kind : Action -> Kind,
//              gloc, lloc : Action -> Loc,
//              callmap, retmap : Thr -> Val,
//              wv, rv : Action -> Val,
//              hb, sb, mo, rf : Action -> Action,
//              guar, deny : Action -> Action | {
//      valid[dom, kind, gloc, lloc, callmap, retmap, wv, rv, ^hb, sb, mo, rf]
//
//      // Non-atomics turned off.
//      // DRF[dom, kind, loc, wv, rv, ^hb, sb, mo, rf]
//
//      // prune boring contexts
//      cutR[dom, kind, gloc, wv, rv, ^hb, sb, mo, rf]
//      cutW[dom, kind, gloc, wv, rv, ^hb, sb, mo, rf]
//      //some Extern & Read
//      //some Intern.loc & (Extern & Read).loc
//
//      // Sanity conditions
//      dom = Action
//      Loc = dom.(lloc + gloc)
//      is_core[hb]
//      is_core[sb]
//
//      // History stuff
//      preexecWF[dom, kind, gloc, lloc, sb]
//      one Call & dom
//      one Ret & dom
//      //some Extern & kind.Read
//
//      some g : Glob & Atomic, t : Thr |
//        read2[dom - Extern, kind, gloc, lloc, sb, g, t]
//
//      guar = getguar[dom, hb]
//      deny = getdeny[dom, kind, gloc, wv, rv, ^hb, sb, mo, rf]
//   }
// } for 8 but exactly 2 Extern
//
// run hist_incl_run {
//   some dom : set Action, hb, sb, mo, rf : Action -> Action,
//       // guar, deny : Action -> Action,
//       dom' : set Action, hb', sb', mo', rf' : Action -> Action,
//       guar, guar', deny, deny' : Action -> Action
//     when {
//       interesting_exec[dom,^hb, sb, mo, rf]
//       // some Extern & Write
//
//       valid[dom, ^hb, sb, mo, rf]
//       DRF[dom, ^hb, sb, mo, rf]
//       is_core[hb]
//       is_core[hb']
//       is_core[sb]
//       is_core[sb']
//
//       preexecWF[dom, sb]
//       preexecWF[dom', sb']
//
//       // identical interfaces
//       getinterf[dom] = getinterf[dom']
//
//       // Sanity conditions
//       Action = dom + dom'
//       Loc = dom.loc + dom'.loc
//
//       // Shared call / return
//       one Call & (dom + dom')
//       one Ret & (dom + dom')
//
//       // Code definition
//       some l : Loc, v : Val | {
//         write2[ dom - Extern, sb, l, v]
//         write1[ dom' - Extern, sb', l, v]
//       }
//     } | {
//       valid[dom', ^hb', sb', mo', rf']
//       DRF[dom', ^hb', sb', mo', rf']
//
//       guar = getguar[dom, hb]
//       guar' = getguar[dom', hb']
//       guar' in guar
//
//       deny = getdeny[dom, hb, sb, mo, rf]
//       deny' = getdeny[dom', hb', sb', mo', rf']
//       deny' in deny
//
//       some r1, r2 : Extern & Read, w : Extern & Write |
//          disj[r1, r2, w]
//     }
//   } for 7 but 1 Call, 1 Ret, 0 RMW


add sample to use named_* module

add sample to use named_* module

open named_man_ja [Man]
open named_woman_ja [Woman]

abstract sig Person {
  love: Person
}

abstract sig Man extends Person {
}

abstract sig Woman extends Person {
}

run {
  #Man = 3
  #Woman = 5
} for 10

error: pathspec 'demo_of_named_man.als' did not match any file(s) known to git