All Downloads are FREE. Search and download functionalities are using the official Maven repository.

ch.openchvote.simulator.random.RandomVotingStrategy Maven / Gradle / Ivy

Go to download

This module provides an election simulator class, which can be used for simulating CHVote election events based on various parameters.

There is a newer version: 2.3.1
Show newest version
/*
 * Copyright (C) 2024 Berner Fachhochschule https://e-voting.bfh.ch
 *
 *  - This program is free software: you can redistribute it and/or modify                           -
 *  - it under the terms of the GNU Affero General Public License as published by                    -
 *  - the Free Software Foundation, either version 3 of the License, or                              -
 *  - (at your option) any later version.                                                            -
 *  -                                                                                                -
 *  - This program is distributed in the hope that it will be useful,                                -
 *  - but WITHOUT ANY WARRANTY; without even the implied warranty of                                 -
 *  - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the                                   -
 *  - GNU General Public License for more details.                                                   -
 *  -                                                                                                -
 *  - You should have received a copy of the GNU Affero General Public License                       -
 *  - along with this program. If not, see .                           -
 */
package ch.openchvote.simulator.random;

import ch.openchvote.algorithms.protocols.plain.model.VotingParametersPlain;
import ch.openchvote.algorithms.protocols.writein.model.VotingParametersWriteIn;
import ch.openchvote.algorithms.protocols.writein.model.WriteIn;
import ch.openchvote.simulator.SimulationConfiguration;
import ch.openchvote.utilities.sequence.IntVector;
import ch.openchvote.utilities.sequence.Vector;
import ch.openchvote.utilities.set.IntSet;
import ch.openchvote.utilities.tools.RandomFactory;
import ch.openchvote.voter.VotingStrategy;

import java.util.Random;
import java.util.Set;
import java.util.TreeSet;

/**
 * Instances of this class can be used by a voter to select the candidates in a simulated election event.
 */
public class RandomVotingStrategy implements VotingStrategy {

    private final double p_participation;
    private final Random random;

    /**
     * Constructs a new voting strategy based on a given simulation configuration.
     *
     * @param simulationConfiguration The given simulation configuration
     */
    public RandomVotingStrategy(SimulationConfiguration simulationConfiguration) {
        this(simulationConfiguration.getProbParticipation(), simulationConfiguration.getRandomFactoryMode());
    }

    /**
     * Constructs a new voting strategy. Its behaviour is mainly determined by the node of operation of the random
     * generator, which is initialized by this constructor.
     *
     * @param p_participation The probability of the voter to participate in the election event
     * @param mode            The mode of operation for the random generator
     */
    public RandomVotingStrategy(double p_participation, RandomFactory.Mode mode) {
        this.p_participation = p_participation;
        this.random = RandomFactory.getInstance(mode);
    }

    @Override
    public int getParticipationBit() {
        return (this.random.nextDouble() <= this.p_participation) ? 1 : 0;
    }

    @Override
    public IntSet getSelection(VotingParametersPlain votingParameters) {
        return this.getSelection(votingParameters.get_bold_n(), votingParameters.get_bold_k(), votingParameters.get_bold_hat_e_v(), null);
    }

    @Override
    public IntSet getSelection(VotingParametersWriteIn votingParameters) {
        return this.getSelection(votingParameters.get_bold_n(), votingParameters.get_bold_k(), votingParameters.get_bold_e_hat_v(), votingParameters.get_bold_v());
    }

    @Override
    public Vector getWriteIns(IntSet S, VotingParametersWriteIn votingParameters) {
        return this.getWriteIns(S, votingParameters.get_bold_n(), votingParameters.get_bold_k(), votingParameters.get_bold_e_hat_v(), votingParameters.get_bold_v(), votingParameters.get_bold_z());
    }

    // private helper method for generating the set of candidates
    private IntSet getSelection(IntVector bold_n, IntVector bold_k, IntVector bold_e_hat_v, IntVector bold_v) {
        var S = new TreeSet();
        int t = bold_n.getLength();
        int n_prime = 0;
        for (int l : IntSet.range(1, t)) {
            int n_l = bold_n.getValue(l);
            int k_l = bold_k.getValue(l);
            if (bold_e_hat_v.getValue(l) == 1) {
                this.getSelection(S, n_l, k_l, n_prime, bold_v);
            }
            n_prime = n_prime + n_l;
        }
        return IntSet.of(S);
    }

    // selecting the candidates in case of write-in elections must guarantee the ordering constraints described in Section 9.1.2.2
    private void getSelection(Set S, int n_j, int k_j, int n_prime, IntVector bold_v) {
        int skipped = 0; // number of write-in candidates to skip
        int k = k_j; // remaining number of selections
        int n = n_j; // remaining number of candidates
        int i = n_prime + 1; // current candidate index
        while (k > 0) {
            int v_i = (bold_v == null) ? 0 : bold_v.getValue(i);
            if (v_i == 1 && skipped > 0) {
                skipped--;
            } else if (this.random.nextInt(n) < k) {
                S.add(i);
                k--;
                if (v_i == 0) {
                    skipped++;
                }
            }
            i++;
            n--;
        }
    }

    // private helper method for generating the write-in candidates
    private Vector getWriteIns(IntSet S, IntVector bold_n, IntVector bold_k, IntVector bold_e_hat, IntVector bold_v, IntVector bold_z) {
        var z_prime = bold_e_hat.multiply(bold_z.times(bold_k));
        var builder_bold_s_prime = new Vector.Builder(z_prime);
        int t = bold_n.getLength();
        int n_prime = 0;
        for (int l : IntSet.range(1, t)) {
            var n_l = bold_n.getValue(l);
            var e_hat_l = bold_e_hat.getValue(l);
            var z_l = bold_z.getValue(l);
            if (e_hat_l == 1 && z_l == 1) {
                for (int i : IntSet.range(n_prime + 1, n_prime + n_l)) {
                    var v_i = bold_v.getValue(i);
                    if (S.contains(i)) {
                        if (v_i == 1) {
                            builder_bold_s_prime.add(new WriteIn(this.getRandomFirstName(), this.getRandomLastName()));
                        } else {
                            builder_bold_s_prime.add(WriteIn.EMPTY);
                        }
                    }
                }
            }
            n_prime = n_prime + n_l;
        }
        return builder_bold_s_prime.build();
    }

    // private helper method for generating random first names
    private String getRandomFirstName() {
        int i = this.random.nextInt(FIRST_NAMES.length);
        return FIRST_NAMES[i];
    }

    // private helper method for generating random last names
    private String getRandomLastName() {
        int i = this.random.nextInt(LAST_NAMES.length);
        return LAST_NAMES[i];
    }

    // two arrays of exemplary first and last names
    static private final String[] FIRST_NAMES = {"Eileen", "Lorretta", "Merle", "Brooke", "Sana", "Devorah", "Melaine", "Chantell", "Annamae", "Chong", "Toby", "Jeannie", "Genna", "Reita", "Pierre", "Kary", "Marta", "Josephine", "Glenda", "Suzanne", "Robyn", "Oma", "Tresa", "Eustolia", "Delma", "Tonia", "Kathy", "Lavenia", "Darrick", "Abe", "Patsy", "Eleni", "Lester"};
    static private final String[] LAST_NAMES = {"Jarvie", "Schillaci", "Brass", "Koss", "Birdwell", "Bauch", "Lineberger", "Mencer", "Mitchem", "Dews", "Moreland", "Catlin", "Millette", "Clements", "Bastin", "Riter", "Bhatt", "Aichele", "Funnell", "Frazer", "Bordelon", "Huggard", "Auger", "Comiskey", "Dacosta", "Renegar", "Ringler", "Rodarte", "Naval", "Haydel", "Briant"};

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy