diff --git a/comsoc/Approval.go b/comsoc/Approval.go index e6f3c5ed5da1a0a933b396081f93d4d0e5a89bca..1faee80bdc96540766ecb513292dd5eeb0c35af5 100644 --- a/comsoc/Approval.go +++ b/comsoc/Approval.go @@ -4,11 +4,10 @@ package comsoc // thresholds est un slice d'entiers strictement positifs func ApprovalSWF(p Profile, thresholds []int) (count Count, err error) { count = make(Count) - alts := make([]Alternative, 0) - for i := 1; i <= len(p[0]); i++ { - alts = append(alts, Alternative(i)) + err = checkProfileFromProfile(p) + if err != nil { + return nil, err } - err = checkProfileAlternative(p, alts) for index, alt := range p { for i := 0; i < thresholds[index]; i++ { count[alt[i]] += 1 @@ -19,6 +18,9 @@ func ApprovalSWF(p Profile, thresholds []int) (count Count, err error) { func ApprovalSCF(p Profile, thresholds []int) (bestAlts []Alternative, err error) { alts, err := ApprovalSWF(p, thresholds) + if err != nil { + return nil, err + } bestAlts = maxCount(alts) return } diff --git a/comsoc/Borda.go b/comsoc/Borda.go index 9e16bacbb597ed9665db894ea16f014df81c6305..444f5442cb48277adea1ecf06a7c707e39984fbd 100644 --- a/comsoc/Borda.go +++ b/comsoc/Borda.go @@ -1,15 +1,22 @@ package comsoc -import("fmt") -func BordaSWF(p Profile) (count Count, err error){ +import ( + "fmt" +) + +func BordaSWF(p Profile) (count Count, err error) { count = make(Count) - nAlts := len(p[0]) - for _, row := range p{ - for i:=0; i<nAlts;i++{ - count[row[i]]+=nAlts-1-i + err = checkProfileFromProfile(p) + if err != nil { + return nil, err + } + nAlts := len(p[0]) + for _, row := range p { + for i := 0; i < nAlts; i++ { + count[row[i]] += nAlts - 1 - i } } - return count,nil + return } func BordaSCF(p Profile) (bestAlts []Alternative, err error) { @@ -17,14 +24,14 @@ func BordaSCF(p Profile) (bestAlts []Alternative, err error) { if err != nil { return nil, err } - return maxCount(count), nil -} + return maxCount(count), err +} -func Test_borda(){ - profil := GenerateProfile(3,5) +func Test_borda() { + profil := GenerateProfile(3, 5) fmt.Println("Profil :", profil) - count,_ := BordaSWF(profil) + count, _ := BordaSWF(profil) fmt.Println("Décompte :", count) - winners,_ := BordaSCF(profil) + winners, _ := BordaSCF(profil) fmt.Println("Vainqueur(s) :", winners) -} \ No newline at end of file +} diff --git a/comsoc/CondorcetWinner.go b/comsoc/CondorcetWinner.go index 60cfdd1f2a8cfea06e84c80aab3147a961977530..934f22490a10956661f3e48b35159a179c997b79 100644 --- a/comsoc/CondorcetWinner.go +++ b/comsoc/CondorcetWinner.go @@ -1,5 +1,7 @@ package comsoc +import "errors" + // Gagnant de condorcet, retourne un slice vide ou de 1 élément // A vérifier avec plus d'exemples func CondorcetWinner(p Profile) (bestAlts []Alternative, err error) { @@ -25,5 +27,5 @@ func CondorcetWinner(p Profile) (bestAlts []Alternative, err error) { return []Alternative{alt1}, nil } } - return []Alternative{}, nil + return nil, errors.New("pas de gagnant de Condorcet") } diff --git a/comsoc/HelpFunctions.go b/comsoc/HelpFunctions.go index 3621bd00572494b84f98a8e33c35670340a2eada..fdf1558de2ada2df30618ef0470d711c8eef521f 100644 --- a/comsoc/HelpFunctions.go +++ b/comsoc/HelpFunctions.go @@ -71,13 +71,22 @@ func Test_maxCount() { func checkProfile(prefs []Alternative, alts []Alternative) error { //vérifier if len(prefs) < len(alts) { - return errors.New("Il manque des alternatives") + return errors.New("préférences non complètes") } else if len(prefs) > len(alts) { - return errors.New("Il y a des alternatives en trop.") + return errors.New("alternatives en trop") } else { //vérifier complet for _, element := range alts { if rank(element, prefs) == -1 { - return errors.New("au moins une alternative est absente des préférences") + return errors.New("une des alternatives est absente des préférences") + } + nApp := 0 + for _, pref := range prefs { + if element == pref { + nApp += 1 + } + } + if nApp != 1 { + return errors.New("une alternative apparait plusieurs fois") } } } @@ -95,15 +104,21 @@ func Test_checkProfile() { // vérifie le profil donné, par ex. qu'ils sont tous complets // et que chaque alternative de alts apparaît exactement une fois par préférences func checkProfileAlternative(prefs Profile, alts []Alternative) error { - for _, row := range prefs { - e := checkProfile(row, alts) - if e != nil { - return e - } + for _, pref := range prefs { + return checkProfile(pref, alts) } return nil } +func checkProfileFromProfile(prof Profile) (err error) { + alts := make([]Alternative, 0) + for i := 1; i <= len(prof[0]); i++ { + alts = append(alts, Alternative(i)) + } + err = checkProfileAlternative(prof, alts) + return +} + func Test_checkProfileAlternative() { alts := []Alternative{1, 2, 3, 4, 5} pref1 := []Alternative{5, 3, 1, 4, 2} diff --git a/comsoc/Majority.go b/comsoc/Majority.go index 5f3ecfafd5443e2b7e706bbaf1b0e2e35b5e2a39..cce9c75820f44b6d837977c2e1094be766dd9dcc 100644 --- a/comsoc/Majority.go +++ b/comsoc/Majority.go @@ -1,15 +1,19 @@ package comsoc -//majorité simple +// majorité simple // fonctions de bien-être social (social welfare function, SWF) : // retournent un décompte à partir d'un profil // En utilisation la méthode de la majorité simple func MajoritySWF(p Profile) (count Count, err error) { count = make(Count) + err = checkProfileFromProfile(p) + if err != nil { + return nil, err + } for _, pref := range p { count[pref[0]]++ } - return count, nil + return } func MajoritySCF(p Profile) (bestAlts []Alternative, err error) { @@ -17,5 +21,5 @@ func MajoritySCF(p Profile) (bestAlts []Alternative, err error) { if err != nil { return nil, err } - return maxCount(count), nil + return maxCount(count), err } diff --git a/comsoc/TieBreak.go b/comsoc/TieBreak.go index 872f249ace73e0f3fd8feaeaa47ee8d650901a0e..1edf29af4d410c44ff9586493abdfb0514026341 100644 --- a/comsoc/TieBreak.go +++ b/comsoc/TieBreak.go @@ -1,105 +1,114 @@ - package comsoc -import("fmt") - -func TieBreakFactory(orderedAlts []Alternative) (func ([]Alternative) (Alternative, error)){ - return func (bestAlts []Alternative) (Alternative, error) { - bestAlt := bestAlts[0] - for _,alt:= range bestAlts[1:]{ - if isPref(alt,bestAlt,orderedAlts){ - bestAlt = alt - } + +import "fmt" + +func TieBreakFactory(orderedAlts []Alternative) func([]Alternative) (Alternative, error) { + return func(bestAlts []Alternative) (Alternative, error) { + bestAlt := bestAlts[0] + for _, alt := range bestAlts[1:] { + if isPref(alt, bestAlt, orderedAlts) { + bestAlt = alt } - return bestAlt, nil } + return bestAlt, nil + } } -func Test_tieBreakFactory(){ - orderedAlts := []Alternative{8,9,6,1,3,2} +func Test_tieBreakFactory() { + orderedAlts := []Alternative{8, 9, 6, 1, 3, 2} fmt.Println("Ordre strict :", orderedAlts) - lambda:=TieBreakFactory(orderedAlts) - bestAlts := []Alternative{3,6} + lambda := TieBreakFactory(orderedAlts) + bestAlts := []Alternative{3, 6} fmt.Println("Premières alternatives, à départager :", bestAlts) - bestAlt,_ := lambda(bestAlts) + bestAlt, _ := lambda(bestAlts) fmt.Println("Première alternative :", bestAlt) } -func SWFFactory(swf func (Profile) (Count, error), tb func([]Alternative) (Alternative, error)) (func(Profile) ([]Alternative, error)){ - - return func(p Profile) ([]Alternative, error){ +func SWFFactory(swf func(Profile) (Count, error), tb func([]Alternative) (Alternative, error)) func(Profile) ([]Alternative, error) { + + return func(p Profile) ([]Alternative, error) { //récupération du décompte - count,_ := swf(p) + count, err := swf(p) + if err != nil { + return nil, err + } //préparation de la sortie - var sorted_alts []Alternative + var sortedAlts []Alternative //PARCOURS DU DECOMPTE - for len(count) > 0{ + for len(count) > 0 { //On prend les meilleures alternatives (avant tie break) bestAlts := maxCount(count) //On supprime les meilleures alternatives du décompte - for alt := range bestAlts{ - delete(count, Alternative(alt)) + for alt := range bestAlts { + delete(count, Alternative(alt)) } - //Départage - for len(bestAlts) > 0{ - bestAlt,_ := tb(bestAlts) + //Départage + for len(bestAlts) > 0 { + bestAlt, _ := tb(bestAlts) //ajout de la meilleure alternative post-tie break - sorted_alts = append(sorted_alts, bestAlt) + sortedAlts = append(sortedAlts, bestAlt) //suppression de l'alternative dans bestAlts indice := rank(bestAlt, bestAlts) - bestAlts=append(bestAlts[:indice], bestAlts[indice+1:]...) - //suppression de l'alternativ dans le compte + bestAlts = append(bestAlts[:indice], bestAlts[indice+1:]...) + //suppression de l'alternativ dans le compte delete(count, Alternative(bestAlt)) - } } - return sorted_alts,nil } + return sortedAlts, nil + } } -func Test_sWFFactory(){ +func Test_sWFFactory() { //Définition de l'Ordre strict - orderedAlts := []Alternative{8,9,6,1,3,2} + orderedAlts := []Alternative{8, 9, 6, 1, 3, 2} fmt.Println("Ordre strict :", orderedAlts) //Construction d'un profil avec alternatives ex aequo profil := make([][]Alternative, 2) - profil[0] = []Alternative{1, 2, 3,4,5,6} - profil[1] = []Alternative{3, 2, 1,4,5,6} + profil[0] = []Alternative{1, 2, 3, 4, 5, 6} + profil[1] = []Alternative{3, 2, 1, 4, 5, 6} fmt.Println("Profil :", profil) //Construction de la fonction Tie Break - lambda:=TieBreakFactory(orderedAlts) + lambda := TieBreakFactory(orderedAlts) //Construction de la Social Welfare Factory à partir de la fonction swf + la fonction de TieBreak - mu := SWFFactory(BordaSWF,lambda) - //Construction d'une fonction - sorted_alts,_ := mu(profil) + mu := SWFFactory(BordaSWF, lambda) + //Construction d'une fonction + sorted_alts, _ := mu(profil) fmt.Println("Alternatives strictement ordonnées selon la méthode de Borda :", sorted_alts) } -func SCFFactory(scf func (p Profile) ([]Alternative, error),tb func ([]Alternative) (Alternative, error)) (func(Profile) (Alternative, error)){ - return func(p Profile) (Alternative, error){ - //récupération des meilleures alternatives - bestAlts,_ := scf(p) - //récupération de la meilleure alternative - bestAlt,_ := tb(bestAlts) - return bestAlt,nil +func SCFFactory(scf func(p Profile) ([]Alternative, error), tb func([]Alternative) (Alternative, error)) func(Profile) (Alternative, error) { + return func(p Profile) (Alternative, error) { + //récupération des meilleures alternatives + bestAlts, err1 := scf(p) + if err1 != nil { + return Alternative(0), err1 + } + //récupération de la meilleure alternative + bestAlt, err2 := tb(bestAlts) + if err2 != nil { + return Alternative(0), err2 + } + return bestAlt, nil } } -func Test_sCFFactory(){ +func Test_sCFFactory() { //Définition de l'Ordre strict - orderedAlts := []Alternative{8,9,6,1,3,2} + orderedAlts := []Alternative{8, 9, 6, 1, 3, 2} fmt.Println("Ordre strict :", orderedAlts) //Construction d'un profil avec alternatives ex aequo profil := make([][]Alternative, 2) - profil[0] = []Alternative{1, 2, 3,4,5,6} - profil[1] = []Alternative{3, 2, 1,4,5,6} + profil[0] = []Alternative{1, 2, 3, 4, 5, 6} + profil[1] = []Alternative{3, 2, 1, 4, 5, 6} fmt.Println("Profil :", profil) //Construction de la fonction Tie Break - lambda:=TieBreakFactory(orderedAlts) - mu := SCFFactory(BordaSCF,lambda) - //Construction d'une fonction - best_Alt,_ := mu(profil) + lambda := TieBreakFactory(orderedAlts) + mu := SCFFactory(BordaSCF, lambda) + //Construction d'une fonction + best_Alt, _ := mu(profil) fmt.Println("Meilleure alternative selon la méthode de Borda :", best_Alt) -} \ No newline at end of file +}