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.")
Beispiel #5
0
        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}")