def test_random_profile(num_voters, num_cand, prob_dist_id): prob_distribution = {"id": prob_dist_id} if prob_dist_id in ["IC fixed-size"]: prob_distribution.update({"setsize": 3}) if prob_dist_id in ["Truncated Mallows"]: prob_distribution.update({"setsize": 3, "dispersion": 0.2}) if prob_dist_id in ["Truncated Urn", "Urn fixed-size"]: prob_distribution.update({"setsize": 3, "replace": 0.2}) if prob_dist_id in ["Urn"]: prob_distribution.update({"p": 0.3, "replace": 0.2}) if prob_dist_id in ["IC", "Disjoint Resampling"]: prob_distribution.update({"p": 0.2}) if prob_dist_id in ["Resampling", "Noise"]: prob_distribution.update({"p": 0.2, "phi": 0.5}) if prob_dist_id in ["Euclidean VCR"]: prob_distribution.update({ "voter_prob_distribution": PointProbabilityDistribution(name="2d_disc"), "candidate_prob_distribution": PointProbabilityDistribution(name="2d_disc"), "voter_radius": 0.1, "candidate_radius": 0.1, }) if prob_dist_id in ["Euclidean fixed-size"]: prob_distribution.update({ "voter_prob_distribution": PointProbabilityDistribution(name="2d_disc"), "candidate_prob_distribution": PointProbabilityDistribution(name="2d_disc"), "setsize": 3, }) if prob_dist_id in ["Euclidean Threshold"]: prob_distribution.update({ "voter_prob_distribution": PointProbabilityDistribution(name="2d_disc"), "candidate_prob_distribution": PointProbabilityDistribution(name="2d_disc"), "threshold": 1.2, }) profile = generate.random_profile(num_voters, num_cand, prob_distribution) assert isinstance(profile, Profile) assert len(profile) == num_voters, "wrong number of voters" if "setsize" in prob_distribution: for voter in profile: assert len(voter.approved) == prob_distribution["setsize"] if "threshold" in prob_distribution: for voter in profile: assert len(voter.approved) >= 1
def test_euclidean_errors(prob_distribution): prob_distribution[ "voter_prob_distribution"] = PointProbabilityDistribution( "1d_interval", center_point=[0]) prob_distribution[ "candidate_prob_distribution"] = PointProbabilityDistribution( "2d_square", center_point=[0, 2]) with pytest.raises(ValueError): generate.random_profile(num_voters=10, num_cand=20, prob_distribution=prob_distribution) prob_distribution[ "voter_prob_distribution"] = PointProbabilityDistribution( "3d_cube", center_point=[0, 0, 0], width=3) prob_distribution[ "candidate_prob_distribution"] = PointProbabilityDistribution( "2d_disc", center_point=[0, 2]) with pytest.raises(ValueError): generate.random_profile(num_voters=10, num_cand=20, prob_distribution=prob_distribution) prob_distribution["candidate_prob_distribution"] = None prob_distribution["candidate_points"] = [[0, 2, 3], [1, 2]] with pytest.raises(ValueError): generate.random_profile(num_voters=10, num_cand=20, prob_distribution=prob_distribution) with pytest.raises(ValueError): generate.random_point( PointProbabilityDistribution("3d_object", center_point=[0, 0], width=1)) with pytest.raises(ValueError): PointProbabilityDistribution("3dcube", center_point=[0, 0], width=1) with pytest.raises(ValueError): PointProbabilityDistribution("threed_cube", center_point=[0, 0], width=1) with pytest.raises(ValueError): generate.random_profile(num_voters=10, num_cand=20, prob_distribution=prob_distribution)
def test_euclidean(num_voters, num_cand, prob_distribution, point_distribution): print(prob_distribution) assert "id" in prob_distribution.keys() print("passed") prob_distribution["voter_prob_distribution"] = point_distribution prob_distribution["candidate_prob_distribution"] = point_distribution if point_distribution is None: prob_distribution["candidate_points"] = [[0, 2, 3], [1, 2, -1] ] * (num_cand // 2) prob_distribution["voter_points"] = [[0, 1, 3], [1, 2, 3] ] * (num_voters // 2) print(prob_distribution) profile = generate.random_profile(num_voters, num_cand, prob_distribution) assert isinstance(profile, Profile) assert len(profile) == num_voters, "wrong number of voters" if "setsize" in prob_distribution: for voter in profile: assert len(voter.approved) == prob_distribution["setsize"] if "threshold" in prob_distribution: for voter in profile: assert len(voter.approved) >= 1
def generate_abc_yaml_testinstances( batchname, committeesizes, num_voters_values, num_cand_values, prob_distributions, av_neq_pav=False, ): generate.rng = np.random.default_rng(24121838) # seed for numpy RNG parameter_tuples = [] for committeesize, num_voters, num_cand, prob_distribution in product( committeesizes, num_voters_values, num_cand_values, prob_distributions ): if committeesize >= num_cand: continue parameter_tuples.append((num_voters, num_cand, prob_distribution, committeesize)) parameter_tuples.sort(key=itemgetter(1)) print(f"Generating {len(parameter_tuples)} instances for batch {batchname}...") num_instances = 0 for index, (num_voters, num_cand, prob_distribution, committeesize) in enumerate( parameter_tuples ): num_instances += 1 # write instance to .abc.yaml file currdir = os.path.dirname(os.path.abspath(__file__)) filename = currdir + f"/instance{batchname}{index:04d}.abc.yaml" print(f"generating {filename} ({prob_distribution})") while True: profile = generate.random_profile(num_voters, num_cand, prob_distribution) committees_av = abcrules.compute("av", profile, committeesize, resolute=False) committees_pav = abcrules.compute("pav", profile, committeesize, resolute=False) if not av_neq_pav: break intersection = set(tuple(sorted(committee)) for committee in committees_pav) & set( tuple(sorted(committee)) for committee in committees_av ) if not intersection: break rule_instances = [] for rule_id in abcrules.MAIN_RULE_IDS: rule = abcrules.Rule(rule_id) # if irresolute (resolute = False) is supported, then "result" should be # the list of committees returned for resolute=False. if False in rule.resolute_values: resolute = False else: resolute = True if rule_id == "rsd": committees = None # result is random, not sensible for unit tests elif rule_id == "leximaxphragmen" and (num_cand > 7 or num_voters > 8): committees = None # too slow else: committees = abcrules.compute(rule_id, profile, committeesize, resolute=resolute) for resolute in rule.resolute_values: rule_instances.append( {"rule_id": rule_id, "resolute": resolute, "result": committees} ) fileio.write_abcvoting_instance_to_yaml_file( filename, profile, committeesize=committeesize, description=( f"profile generated via prob_distribution={prob_distribution}, " f"num_voters={num_voters}, " f"num_cand={num_cand}" ), compute_instances=rule_instances, ) print("Done.")
candidate_radius = radius / 2 prob_distributions.append( { "id": "Euclidean VCR", "voter_prob_distribution": point_distribution, "candidate_prob_distribution": point_distribution, "voter_radius": voter_radius, "candidate_radius": candidate_radius, } ) print( f"Generating {len(prob_distributions)} profiles " f"with {num_voters} voters and {num_cand} candidates.\n" "This may take a while...\n" ) # generate profiles profiles = [] for prob_distribution in prob_distributions: profile = generate.random_profile(num_voters, num_cand, prob_distribution) profiles.append((prob_distribution, profile)) # print statistics print(f"Done. Generated {len(profiles)} profiles.") prob_dist_ids = sorted({prob_dist["id"] for prob_dist, profile in profiles}) for prob_dist_id in prob_dist_ids: count = len([profile for prob_dist, profile in profiles if prob_dist["id"] == prob_dist_id]) print(f" {count} profiles via {prob_dist_id}")