Skip to content
Snippets Groups Projects
Commit 617240ad authored by Millian Poquet's avatar Millian Poquet
Browse files

wip: stud proj

parent 961d0133
No related branches found
No related tags found
No related merge requests found
{ {
inputs = { inputs = {
nixpkgs.url = "github:nixos/nixpkgs?ref=23.05"; nixpkgs.url = "github:nixos/nixpkgs?ref=branch-off-24.11";
flake-utils.url = "github:numtide/flake-utils"; flake-utils.url = "github:numtide/flake-utils";
typst = { typst = {
url = "github:typst/typst/main"; url = "github:typst/typst/main";
......
#!/usr/bin/env python3
import collections
import copy
import random
import numpy as np
import pandas as pd
def moodle_poll_csv_filename_to_df(filename, vote_field='Q01_preference'):
df = pd.read_csv(filename)
df.rename(columns={
'Nom complet': 'voter_name',
vote_field: 'vote',
'Soumis le :': 'date',
}, inplace=True)
df = df[['date', 'voter_name', 'vote']]
return df
def check_vote(vote):
if not isinstance(vote, str):
return False
if len(vote) != 4:
return False
if ''.join(sorted(vote)) != '1234':
return False
return True
def serial_dictatorship(vote_df):
empty_slots = {str(x+1):3 for x in range(4)}
alloc = []
for _, row in vote_df.iterrows():
allocated = False
for topic in row['vote']:
if empty_slots[topic] > 0:
alloc.append((row['voter_name'], topic))
empty_slots[topic] = empty_slots[topic] - 1
allocated = True
break
if not allocated:
raise Exception('Could not find any available slot for student {}, whose vote is {}'.format(row['voter_name'], row['vote']))
return sorted(alloc)
def alloc_rank(vote, got):
# returns the rank of the choice that a voter (that voted 'vote') obtained in a given allocation
# 0 is the best, 3 the worst
for rank, value in enumerate(vote):
if value == got:
return rank
raise Exception(f'no rank found from vote={vote} when got={got}')
def compare_alloc(allocA, allocB, vote_df):
# return how many voters prefer A to B. can be negative or 0.
prefA = 0
prefB = 0
for _, row in vote_df.iterrows():
rankA = alloc_rank(row['vote'], allocA[row['voter_name']])
rankB = alloc_rank(row['vote'], allocA[row['voter_name']])
if rankA < rankB:
prefA += 1
elif rankB < rankA:
prefB += 1
return prefA, prefB
candidates = ['1', '2', '3', '4']
# example from CSV
#df = moodle_poll_csv_filename_to_df('./proj-preferences.csv')
#df_valid = df[df['vote'].apply(check_vote)]
#df_latest = df_valid.sort_values(by='date').groupby('voter_name', as_index=False).last()
# random data
random_data = []
random.seed(2)
for stud_id in range(12):
stud_name = f"stud{stud_id:02d}"
stud_vote = copy.deepcopy(candidates)
random.shuffle(stud_vote)
stud_vote = ''.join(stud_vote)
random_data.append({'voter_name': stud_name, 'vote': stud_vote})
random_df = pd.DataFrame(random_data)
# generate many allocations from various random order traversal of votes, only keep unique solutions
df = random_df
pareto_optimal_allocs = dict()
alloc_values_seen = set()
for seed in range(100):
alloc_name = f'seed{seed:03d}'
reordered_df = df.sample(frac=1, random_state=seed)
alloc = serial_dictatorship(reordered_df)
alloc_values = ''.join([topic for stud,topic in alloc])
if alloc_values not in alloc_values_seen:
pareto_optimal_allocs[alloc_name] = alloc
alloc_values_seen.add(alloc_values)
print(len(alloc_values_seen))
\ No newline at end of file
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment