stateStof
elected: setof Candidate
excluded: setof Candidate
continuing: setof Candidate
stages: seqof Stage
quota: real
record: seqof Record_entry
next_choice : seqof Candidate_names inv s ==
{cand.name | cand inset s.elected union s.excluded union s.continuing} =
Cand_names and
disjoint({s.elected, s.excluded, s.continuing}) and
(forall cand1 inset s.elected union s.excluded union s.continuing,
cand2 inset s.elected union s.excluded union s.continuing &
(cand1 = cand2) <=> (cand1.name = cand2.name)) init s == s =
mk_St({mk_Candidate(nm,{|->},[])|nm inset Cand_names}, --{},
{},{},[],42,[],[]) end
functions
mult_p_sum:setof (nat * Parcel) -> nat
mult_p_sum(s) == if s = {} then 0 elselet mk_(m,pa) inset s in
(card(dom pa) * m) + mult_p_sum(s \ {mk_(m,pa)});
size: Parcel -> nat
size(p) == let mults = rng p in let mult_p = {mk_(m, p :> {m}) | m inset mults} in
mult_p_sum(mult_p);
construct_sub_parcels: Value * Parcel * Candidate * setof Candidate
-> Sub_parcel_bundle
construct_sub_parcels(val,parcel,discontinuing,continuing_candidates) == let names = {candidate.name | candidate inset continuing_candidates} in let sub_parcel_map = { n |-> mk_Sub_parcel({ v |-> parcel(v) | v insetdom
parcel & next_preference(n,v,names)},val)
| n inset names} in let non_empty_sub_parcel_map = { n |-> sub_parcel_map(n) | n inset dom sub_parcel_map & sub_parcel_map(n).votes <> {|->}} in
mk_Sub_parcel_bundle(non_empty_sub_parcel_map,
mk_Sub_parcel(non_transferable_papers(parcel,
discontinuing.name, names),1.0),0);
next_preference: Candidate_names * Voting_paper * setof Candidate_names -> bool
next_preference(name,vote,continuing) == if name insetdom vote thenexists i insetrng vote &
(vote(name) = i and dom (vote :> {1,...,i-1}) inter continuing = {}) elsefalse;
construct_bundle_for_transfer:real * Value * Parcel * Candidate * setof Candidate -> Sub_parcel_bundle
construct_bundle_for_transfer(surplus, old_value, old_votes, disc, cont_cands)
== let new_sub_parcels = construct_sub_parcels(1.00, old_votes,
disc, cont_cands) in let total_no_of_trans_votes = size(old_votes) -
size(new_sub_parcels.non_transferable.votes) in let total_val_trans_votes = total_no_of_trans_votes * old_value in let transf_val = calc_transf_value(surplus,total_val_trans_votes,
old_value,total_no_of_trans_votes) in let sub_parcels = { n |->
mk_Sub_parcel(new_sub_parcels.sub_parcels(n).votes,
transf_val) | n insetdom new_sub_parcels.sub_parcels},
loss_of_value = calc_loss_of_value(surplus,
total_val_trans_votes,total_no_of_trans_votes, old_value),
non_trans_val = calc_non_transf_value(surplus,
total_val_trans_votes) in
mk_Sub_parcel_bundle(sub_parcels,
mk_Sub_parcel(new_sub_parcels.non_transferable.votes,
non_trans_val),
loss_of_value);
calc_transf_value: real * Value * Value * nat -> Value
calc_transf_value(surplus,total_value,old_value, total_no) == if surplus < total_value then (floor((100*surplus)/total_no))/100 else old_value;
calc_loss_of_value: real * Value * nat * Value -> real
calc_loss_of_value(surplus,total_value,total_number,old_value) == if surplus < total_value then (surplus/total_number) -
(floor(100*surplus*old_value/total_value))/100 else 0;
calc_non_transf_value: real * Value -> Value
calc_non_transf_value(surplus,total_value) == if surplus > total_value then surplus - total_value else 0;
redistribute_parcels: Candset * Sub_parcel_bundle -> Candset
redistribute_parcels(previous_collection,bundle) ==
{mu(candidate, transferred_votes |->
[bundle.sub_parcels(n)]^candidate.transferred_votes)|
candidate inset previous_collection,
n insetdom bundle.sub_parcels &
candidate.name = n} union
{candidate| candidate inset previous_collection &
candidate.name notinsetdom bundle.sub_parcels} pre dom bundle.sub_parcels subset {candidate.name |
candidate inset
previous_collection};
score_sort: Stage -> Stage
score_sort(sta) == cases sta:
[] -> sta,
[e] -> sta, others -> let sta1^sta2 inset {sta} bestabs (len sta1 - len sta2) < 2 in let sta_l = score_sort(sta1),
sta_r = score_sort(sta2) in
score_merge(sta_l, sta_r) end;
construct_new_stage:Stage * Candidate_names * Sub_parcel_bundle -> Stage
construct_new_stage(old_stage,discontinuing, bundle) == let cands_with_more_votes = dom bundle.sub_parcels in let unsorted_scores =
{ mk_Score(name,old_count + bundle.sub_parcels(name).value *
size(bundle.sub_parcels(name).votes)) |
mk_Score(name,old_count) inseq old_stage &
name inset cands_with_more_votes}
union
{sc | sc inseq old_stage & sc.name notinset cands_with_more_votes } in
score_sort(set_seq(unsorted_scores));
exists_non_deferable_surplus: (seqof Stage) * real -> bool
exists_non_deferable_surplus(stages,quota) ==
(hd (hd stages)).count >= quota and not defer_transfer_of_surplus(quota, hd stages);
trailing_candidate: Candidate_names * seq1of Stage -> bool
trailing_candidate(name,all_stages) == let trailing_count = (stage_bk(hd all_stages)).count in let lowest = { score.name | score inseqhd all_stages &
score.count = trailing_count} in exists i insetinds all_stages &
(sole_trailer(all_stages(i),name,lowest) and forall j inset {i+1,...,len all_stages}, other inset lowest & not (sole_trailer(all_stages(j),other,lowest)));
sole_trailer: Stage * Candidate_names * setof Candidate_names -> bool
sole_trailer(stage,name,lowest) == let cand = iota c inseq stage & c.name = name in let lowest_scores = {sc | sc inseq stage & sc.name inset lowest} \ {cand} in forall sc inset lowest_scores & cand.count < sc.count;
non_transferable_paper: Voting_paper * Candidate_names * setof Candidate_names -> bool
non_transferable_paper(paper,discontinuing,continuing_names) == dom (paper :-> {1}) inter continuing_names = {} or let s = (rng( paper :-> {1,...,(paper(discontinuing))})) in if s = {} thentrue elselet m = min(s) in
(carddom (paper :> {m}) > 1 or
m - 1 notinsetrng paper);
min: set1 ofreal -> real
min(s) == let m inset s in ifcard s = 1 then m elselet sm = min (s \ {m}) in if m < sm then m else sm;
last_vacancy_fillable: (setof Candidate) * (seqof Stage) * real -> bool
last_vacancy_fillable(continuing,stages, quota) == let continuing_names = {c.name | c inset continuing} in let continuing_scores = [s | s inseqhd stages &
s.name inset continuing_names],
surplus_scores = [s | s inseqhd stages & s.count > quota] in exists i insetinds continuing_scores &
continuing_scores(i).count >
sum([continuing_scores(j).count |
j inset (inds continuing_scores \ {i})]) +
sum([ss.count - quota | ss inseq surplus_scores]);
make_result_sheet: seqof Stage * real * seqof Record_entry * setof Candidate_names -> Result_sheet
make_result_sheet(stages, quota, record, elected) == letresult: nat1 -> Result result(i) == iflen stages(i+1) > len stages(i) thenlet excluded = iota ex inset Cand_names &
ex inset { sc.name |
sc inseq stages(i+1) &
(forall osc inseq stages(i) &
osc.name <> sc.name)} in
mk_Result(record(i+1).scores,nil,excluded) elselet transferred = iota tf inset Cand_names &
tf inset { sc.name |
sc inseq stages(i+1) &
mk_Score(sc.name,quota) insetelems stages(i) and sc.count > quota} in
mk_Result(record(i+1).scores,transferred,nil) in
mk_Result_sheet([result(len record - j) | j inset {1,...,len record -
1}],elected);
sp_set_seq: setof Sub_parcel -> seqof Sub_parcel
sp_set_seq(s) == if s = {} then [] elselet e inset s in [e]^(sp_set_seq (s\{e}));
sub_parcels_sort: seqof Sub_parcel -> seqof Sub_parcel
sub_parcels_sort(sps) == cases sps:
[] -> sps,
[e] -> sps, others -> let sps1^sps2 inset {sps} bestabs (len sps1 - len sps2) < 2 in let sps_l = sub_parcels_sort(sps1),
sps_r = sub_parcels_sort(sps2) in
sub_parcels_merge(sps_l, sps_r) end;
PREPARE_ELECTION: Parcel ==> ()
PREPARE_ELECTION(votes) ==
(dcl curr_cont:Candset := sort_papers(votes, Cand_names);
excluded := {};
continuing := curr_cont;
next_choice := rand_choice;
elected := {};
stages := [build_first_stage(curr_cont)];
quota := two_decimal_places(size(votes)/(Number_of_vacancies + 1));
record := [mk_Record_entry(elemshd stages,0,0)]; let nc = number_of_candidates_satisfying_quota(curr_cont,stages,quota) in if ((0 < nc) and (nc <= Number_of_vacancies)) then
CHANGE_STATUS_OF_ELECTED_CANDIDATES() elseskip);
ELECT_ALL_REMAINING_CANDIDATES:() ==> ()
ELECT_ALL_REMAINING_CANDIDATES() ==
(elected := elected union continuing;
continuing := {});
PROCESS_SUB_PARCELS:Candidate * seqof Sub_parcel ==> ()
PROCESS_SUB_PARCELS(ex_cand, sub_parcels) ==
( dcl i: nat:=0; dcl non_trans_value: real:=0; dcl bundle: Sub_parcel_bundle:=mk_Sub_parcel_bundle({|->},
mk_Sub_parcel({|->},0.0),0); dcl new_candidates: setof Candidate := continuing \ {ex_cand}; dcl new_stage: Stage := hd stages; while i <> len sub_parcels do
( i:= i+1;
bundle:=
construct_sub_parcels(sub_parcels(i).value,sub_parcels(i).votes,
ex_cand,new_candidates);
non_trans_value:=non_trans_value + size(bundle.non_transferable.votes) *
sub_parcels(i).value;
new_candidates:= redistribute_parcels(new_candidates,bundle);
new_stage:= construct_new_stage(new_stage,ex_cand.name,bundle);
(let no_cands = number_of_candidates_satisfying_quota(new_candidates,
[new_stage],quota) in
(if 0 < no_cands and no_cands <= number_of_remaining_vacancies
({e.name | e inset elected}) thenlet xs_quota_scs = {sc.name | sc inseq
new_stage & sc.count >= quota} in let new_elected = { cand | cand inset new_candidates &
cand.name inset xs_quota_scs} in
(elected:=elected union new_elected;
new_candidates:=new_candidates \ new_elected) elseskip)));
continuing:= new_candidates;
excluded:=excluded union {ex_cand};
record:= [mk_Record_entry( elems new_stage union
{score|score inset (hd record).scores &
score.name notinset
{sc.name | sc inseq new_stage}} union
{mk_Score(ex_cand.name,0)},
non_trans_value,0)]^record;
stages:= [[ns | ns inseq new_stage & ns.name <> ex_cand.name]]^stages);
ELECT_LAST_CANDIDATE:() ==> ()
ELECT_LAST_CANDIDATE() ==
(dcl elected_candidate:Candidate := iota leader inset continuing &
leader.name = ((hd stages)(Number_of_vacancies)).name;
elected := elected union {elected_candidate};
continuing := continuing \ {elected_candidate}) pre last_vacancy_fillable(continuing,stages,quota);
TRANSFER_SURPLUS:() ==> ()
TRANSFER_SURPLUS() ==
(dcl name:Candidate_names := CHOOSE_SURPLUS_TO_TRANSFER(); def candidate = iota c inset elected & c.name = name in def surplus = (hdhd stages).count - quota;
sub_parcel = if surplus_from_original_votes(candidate) then mk_Sub_parcel(candidate.original_votes,1.0) elsehd candidate.transferred_votes in def sub_parcel_bundle = construct_bundle_for_transfer(surplus,
sub_parcel.value,
sub_parcel.votes,candidate,continuing) in def new_stage = construct_new_stage(
[mk_Score(name,quota)]^(
[s | s inseq (hd stages) & s.name <> name]), candidate.name,
sub_parcel_bundle) in def curr_cont = redistribute_parcels(continuing \ {candidate},
sub_parcel_bundle) in
(stages := [new_stage]^stages;
record := [mk_Record_entry( elems new_stage union
{score| score inset (hd record).scores &
score.name notinset {sc.name|sc inseq
new_stage}},
sub_parcel_bundle.non_transferable.value,
sub_parcel_bundle.loss_of_value)]^record;
continuing := curr_cont; let nc = number_of_candidates_satisfying_quota(curr_cont,stages,quota) in if 0 < nc and nc <= Number_of_vacancies then (CHANGE_STATUS_OF_ELECTED_CANDIDATES()))) pre exists_non_deferable_surplus(stages,quota);
EXCLUDE_CANDIDATE:() ==> ()
EXCLUDE_CANDIDATE() == let name = CHOOSE_CANDIDATE_TO_EXCLUDE() in let excluded_candidate = iota c inset continuing &
c.name = name in let sorted_sub_parcels =
sub_parcels_sort(sp_set_seq(elems excluded_candidate.transferred_votes union
{mk_Sub_parcel(excluded_candidate.original_votes,1.0)})) in
PROCESS_SUB_PARCELS(excluded_candidate,sorted_sub_parcels);
ELECT_CANDIDATES:() ==> ()
ELECT_CANDIDATES() == def nc = number_of_continuing_candidates({c.name | c inset continuing});
nv = number_of_remaining_vacancies({e.name | e inset elected});
nq = number_of_candidates_satisfying_quota(continuing,stages,quota) in if nc = nv then ELECT_ALL_REMAINING_CANDIDATES() elseif (0< nq and nq <= nv) then CHANGE_STATUS_OF_ELECTED_CANDIDATES() elseif (nv = 1 and
last_vacancy_fillable(continuing,stages,quota)) then ELECT_LAST_CANDIDATE() elseif exists_non_deferable_surplus(stages,quota) then TRANSFER_SURPLUS() else EXCLUDE_CANDIDATE();
CONDUCT_ELECTION: Parcel ==> Result_sheet
CONDUCT_ELECTION(votes) ==
(PREPARE_ELECTION(votes); while (card elected <> Number_of_vacancies) and
(card continuing > 0) do
ELECT_CANDIDATES(); return make_result_sheet(stages,quota,record,{e.name | e inset elected}));
CHANGE_STATUS_OF_ELECTED_CANDIDATES:() ==> ()
CHANGE_STATUS_OF_ELECTED_CANDIDATES() == let xs_quota_scs = {sc.name | sc inseqhd stages & sc.count >= quota} in def candidates_satisfying_quota = {candidate | candidate inset
continuing & candidate.name inset xs_quota_scs} in
(elected := candidates_satisfying_quota union elected;
continuing := continuing \ candidates_satisfying_quota) pre number_of_candidates_satisfying_quota(continuing,stages,quota) <=
number_of_remaining_vacancies({e.name | e inset elected})
¤ Dauer der Verarbeitung: 0.16 Sekunden
(vorverarbeitet)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung ist noch experimentell.