예제 #1
0
 // Creates an infinite sequence of normally-distributed voters.
 public static IEnumerable <VoterFactory> Normal(int candidateCount, Random random)
 {
     while (true)
     {
         yield return(VoterFactory.Normal(candidateCount, random));
     }
 }
예제 #2
0
        /*
         *  This creates electorates based on a Polya/Hoppe/Dirichlet model, with mutation.
         *  You start with an "urn" of `seedVoter` voters from `seedModel`,
         *  plus `alpha` "wildcard" voters. Then you draw a voter from the urn,
         *  clone and mutate them, and put the original and clone back into the urn.
         *  If you draw a "wildcard", use `seedModel` to make a new voter.
         *  https://github.com/electionscience/vse-sim/blob/1d7e48f639fd5ffcf84883dce0873aa7d6fa6794/voterModels.py#L204
         */
        public static IEnumerable <VoterFactory> PolyaModel(this IEnumerable <VoterFactory> seedModel, Random random, int seedVoters = 2, int alpha = 1, double mutantFactor = .2)
        {
            if (seedModel == null)
            {
                throw new ArgumentNullException(nameof(seedModel));
            }
            if (seedVoters < 1)
            {
                throw new ArgumentException(nameof(seedVoters), "Must be positive.");
            }
            if (alpha < 0)
            {
                throw new ArgumentException(nameof(alpha), "Must be non-negative.");
            }

            using (var seedEnumerator = seedModel.GetEnumerator())
            {
                var urn = new List <VoterFactory>();

                for (int i = 0; i < seedVoters; i++)
                {
                    yield return(GetNext());
                }

                while (true)
                {
                    var i = random.Next(urn.Count + alpha);

                    if (i < urn.Count)
                    {
                        var mutant = urn[i].HybridWith(VoterFactory.Normal(urn[i].CandidateCount, random), mutantFactor);
                        urn.Add(mutant);
                        yield return(mutant);
                    }
                    else
                    {
                        yield return(GetNext());
                    }
                }

                VoterFactory GetNext()
                {
                    if (!seedEnumerator.MoveNext())
                    {
                        throw new InvalidOperationException("Expected an infinite enumerable.");
                    }

                    urn.Add(seedEnumerator.Current);
                    return(seedEnumerator.Current);
                }
            }
        }
예제 #3
0
        // https://github.com/electionscience/vse-sim/blob/1d7e48f639fd5ffcf84883dce0873aa7d6fa6794/voterModels.py#L39
        // If both are standard normal to start with, the result will be standard normal too.
        public VoterFactory HybridWith(VoterFactory other, double weight)
        {
            if (other == null)
            {
                throw new ArgumentNullException(nameof(other));
            }
            if (other.m_utilities.Length != m_utilities.Length)
            {
                throw new ArgumentException(nameof(other), "May only combine voter factories with the same initial conditions.");
            }

            var combinedUtilities = new double[m_utilities.Length];
            var denominator       = Math.Sqrt(1 + weight * weight);

            for (int i = 0; i < m_utilities.Length; i++)
            {
                combinedUtilities[i] = (m_utilities[i] + weight * other.m_utilities[i]) / denominator;
            }

            return(new VoterFactory(combinedUtilities));
        }
예제 #4
0
        // Weights an electorate based on a common "quality" factor for each candidate which spans ideology
        public static IEnumerable <VoterFactory> Quality(this IEnumerable <VoterFactory> source, Random random, double weight = .5)
        {
            using (var sourceEnumerator = source.GetEnumerator())
            {
                if (!sourceEnumerator.MoveNext())
                {
                    throw new InvalidOperationException("Expected an infinite enumerable.");
                }

                var quality = VoterFactory.Normal(sourceEnumerator.Current.CandidateCount, random);

                while (true)
                {
                    yield return(sourceEnumerator.Current.HybridWith(quality, weight));

                    if (!sourceEnumerator.MoveNext())
                    {
                        throw new InvalidOperationException("Expected an infinite enumerable.");
                    }
                }
            }
        }