Comparaison des systèmes de votes
Voici une liste des candidats (un par colone) et des préférences des votants (un classement par ligne, ou chaque électeur met une note à chaque candidat)
Résultats
Chaque système nous sort une liste de couples candidats/note.
Nous souhaitons plusieurs propriétés dans un système de vote :
- La confiance
- L'alternance politique
- Se présenter ne doit pas désservir nos idées
- Le vote utile ne doit pas être possible (les votants ne doivent pas avoir intéret à mentir
- Si un candidat est majoritaire, il doit être élu
- L'élu ne doit pas pouvoir perdre un second tour contre un autre candidat
- On ne doit pas pouvoir acheter un vote, ni menacer (le vote doit être secret, et on ne doit pas pouvoir techniquement prouver son vote)
Voici le code ocaml qui sert pour cette simulation
let sort_result li = List.sort (fun (_, a) (_, b) -> b - a) li
let list_candidats_to_scores candidats votes = (* bulletins de vote => liste de couples nom, score *)
Array.map (fun candidat -> candidat, List.length (List.filter (fun v -> v = candidat) votes)) candidats |> Array.to_list |> sort_result
let uninominal_1tour candidats preferences = List.map List.hd preferences |> list_candidats_to_scores candidats
let uninominal_2tours candidats preferences =
match uninominal_1tour candidats preferences with
| (c1, _)::(c2, _)::_ -> List.map (fun p -> List.find_opt (fun c -> c = c1 || c = c2) p |> un_opt) preferences |> list_candidats_to_scores candidats
| x -> x
let remove_worst candidats preferences =
let nth = List.length (List.hd preferences) in
let (worst, _)::_ = list_candidats_to_scores candidats (List.map (fun x -> List.nth x (nth - 1)) preferences)
in List.map (fun p -> List.filter ((<>) worst) p) preferences;;
let australian_legislatif0 candidats preferences =
let rec f = function
| ([x]::_ ) as prefs -> list_candidats_to_scores candidats (List.map List.hd prefs)
| x -> f (remove_worst candidats x)
in f preferences
let australian_legislatif1 candidats preferences =
let nbr_majority = List.length preferences / 2 + 1 in
let rec f x = match uninominal_1tour candidats x with
| [x] -> [x]
| ((winner, score)::_) as li ->
if score >= nbr_majority then li else f (remove_worst candidats x)
in f preferences
let majoritaire preferences_f = (* la liste des candidats doit être triée par nom *)
let median_index = List.length preferences_f / 2 in
let rec f r votes tail_preferences = function
| [] -> failwith "Error"
| [[(nom, vote)]] -> (nom, vote::votes)::r
| [(nom, vote)::tl] -> f ((nom, vote::votes)::r) [] [] (tl::tail_preferences)
| ((_, vote)::tl)::tl2 -> f r (vote::votes) (tl::tail_preferences) tl2 in
let scores = f [] [] [] preferences_f |> List.map (fun (nom, votes) -> nom, List.sort (-) votes) in
let median = List.map (fun (nom, votes) -> nom, List.nth votes median_index) scores in
median |> sort_result
let condorcet candidats preferences_f =
let preferences_f = List.map (Array.of_list @* (List.map snd)) preferences_f in
let score i1 i2 =
let s = List.fold_left (fun acc votes ->
if votes.(i1) = votes.(i2) then acc
else if votes.(i1) > votes.(i2) then acc+1 else acc - 1 ) 0 preferences_f
in if s > 0 then 1 else 0
in
let matrix = candidats |> Array.mapi (fun i1 c1 -> c1, candidats |> Array.mapi (fun i2 c2 -> score i1 i2))
in matrix |> Array.map (fun (c, l) -> c, Array.fold_left (+) 0 l) |> Array.to_list |> sort_result
let bulletins preferences_f = List.map (fun a -> List.sort (fun (_, a) (_, b) -> b - a) a |> List.map fst) preferences_f
