// Assume: // (a) The entire bloc needs to use the same strategy, and // (b) will never use a strategy that leaves them open to a *worse* outcome, and // (c) will only use a non-honest strategy with *some* possibility of a better outcome. public override (List <string> Favorite, List <string> Utility) GetPlausibleStrategies() { var possibleOutcomesByFavoriteStrategy = m_possibleBallots.Length.LengthArray(_ => new Dictionary <PermutationGroup, double[]>()); var possibleOutcomesByUtilityStrategy = m_possibleBallots.Length.LengthArray(_ => new Dictionary <PermutationGroup, double[]>()); foreach (var permuation in GetAllPermutations(m_possibleBallots.Length.LengthArray(i => m_possibleBallots[i].Length))) { var utilities = GetUtility(permuation); for (int i = 0; i < m_possibleBallots.Length; i++) { var key = new PermutationGroup(i, permuation); if (!possibleOutcomesByFavoriteStrategy[i].TryGetValue(key, out var favoriteOutcomes)) { possibleOutcomesByFavoriteStrategy[i][key] = favoriteOutcomes = new double[m_possibleBallots[i].Length]; } if (!possibleOutcomesByUtilityStrategy[i].TryGetValue(key, out var utilityOutcomes)) { possibleOutcomesByUtilityStrategy[i][key] = utilityOutcomes = new double[m_possibleBallots[i].Length]; } favoriteOutcomes[permuation[i]] = utilities.Favorite[i]; utilityOutcomes[permuation[i]] = utilities.Utility[i]; } } return(GetPlausibleStrategies(possibleOutcomesByFavoriteStrategy), GetPlausibleStrategies(possibleOutcomesByUtilityStrategy)); }
public void OptimisedStabiliser() { // This group is a 3x3 grid with symmetric rows and columns var group = new PermutationGroup( new Cycle(new [] { 0, 1 }, new [] { 3, 4 }, new [] { 6, 7 }), new Cycle(new [] { 0, 1, 2 }, new [] { 3, 4, 5 }, new [] { 6, 7, 8 }), new Cycle(new [] { 0, 3 }, new [] { 1, 4 }, new [] { 2, 5 }), new Cycle(new [] { 0, 3, 6 }, new [] { 1, 4, 7 }, new [] { 2, 5, 8 }) ); PermutationGroup stabilisedPointZero; group.OrbitStabiliser(new Points(0), out stabilisedPointZero); stabilisedPointZero.Optimise(); Assert.AreEqual(2, stabilisedPointZero.GeneratorCount); var orbitOfZeroOnStabiliserZero = stabilisedPointZero.Orbit(0); var orbitOfOneOnStabiliserZero = stabilisedPointZero.Orbit(1); var orbitOfFourOnStabiliserZero = stabilisedPointZero.Orbit(4); CollectionAssert.AreEquivalent(new [] { new [] { 0 } }, orbitOfZeroOnStabiliserZero); CollectionAssert.AreEquivalent(new [] { new [] { 1 }, new [] { 2 } }, orbitOfOneOnStabiliserZero); CollectionAssert.AreEquivalent(new [] { new [] { 4 }, new [] { 5 }, new [] { 7 }, new [] { 8 } }, orbitOfFourOnStabiliserZero); }
public void ImageTest() { var group = new PermutationGroup(new Cycle(new [] { 0, 1 }, new [] { 2, 3 }, new [] { 4, 5 }, new [] { 6, 7 }, new [] { 8, 9 })); CollectionAssert.AreEqual(new Image <string>(new [] { "B", "A", "D", "C", "F", "E", "H", "G", "J", "I" }), group.Apply(0, new Image <string>(new [] { "A", "B", "C", "D", "E", "F", "G", "H", "I", "J" }))); }
private void Setup(IAtomContainer atomContainer) { // have to setup the connection table before making the group // otherwise the size may be wrong, but only setup if it doesn't exist IRefinable refinable = GetRefinable(atomContainer); int size = GetVertexCount(); PermutationGroup group = new PermutationGroup(new Permutation(size)); base.Setup(group, new EquitablePartitionRefiner(refinable)); }
public void OrbitStabiliser() { // This group is a 3x3 grid with symmetric rows and columns var group = new PermutationGroup( new Cycle(new [] { 0, 1 }, new [] { 3, 4 }, new [] { 6, 7 }), new Cycle(new [] { 0, 1, 2 }, new [] { 3, 4, 5 }, new [] { 6, 7, 8 }), new Cycle(new [] { 0, 3 }, new [] { 1, 4 }, new [] { 2, 5 }), new Cycle(new [] { 0, 3, 6 }, new [] { 1, 4, 7 }, new [] { 2, 5, 8 }) ); PermutationGroup stabilisedPointZero; var orbitZero = group.OrbitStabiliser(new Points(0), out stabilisedPointZero); CollectionAssert.AreEquivalent(Enumerable.Range(0, 9).Select(i => new [] { i }), orbitZero); var orbitOfZeroOnStabiliserZero = stabilisedPointZero.Orbit(0); var orbitOfOneOnStabiliserZero = stabilisedPointZero.Orbit(1); var orbitOfFourOnStabiliserZero = stabilisedPointZero.Orbit(4); CollectionAssert.AreEquivalent(new [] { new [] { 0 } }, orbitOfZeroOnStabiliserZero); CollectionAssert.AreEquivalent(new [] { new [] { 1 }, new [] { 2 } }, orbitOfOneOnStabiliserZero); CollectionAssert.AreEquivalent(new [] { new [] { 4 }, new [] { 5 }, new [] { 7 }, new [] { 8 } }, orbitOfFourOnStabiliserZero); }
public void CycleTest() { var group = new PermutationGroup(new Cycle(new [] { 0, 1 }, new [] { 2, 3 }, new [] { 4, 5 }, new [] { 6, 7 }, new [] { 8, 9 })); CollectionAssert.AreEqual(new [] { 1, 0, 3, 2, 5, 4, 7, 6, 9, 8 }, group.Apply(0, new Points(new [] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }))); }
public void PointsTest() { var group = new PermutationGroup(new Cycle(new [] { 0, 1 }, new [] { 2, 3 }, new [] { 4, 5 }, new [] { 6, 7 }, new [] { 8, 9 })); CollectionAssert.AreEqual(new Points(new [] { 2, 4, 3 }), group.Apply(0, new Points(new [] { 3, 5, 2 }))); }
/// <summary> /// Speed up the search for the automorphism group using the automorphisms in /// the supplied group. Note that the behaviour of this method is unknown if /// the group does not contain automorphisms... /// </summary> /// <param name="atomContainer">the atom container to use</param> /// <param name="group">the group of known automorphisms</param> /// <returns>the full automorphism group</returns> public PermutationGroup GetAutomorphismGroup(IAtomContainer atomContainer, PermutationGroup group) { Setup(atomContainer, group); base.Refine(refinable.GetInitialPartition()); return(base.GetAutomorphismGroup()); }
private void Setup(IAtomContainer atomContainer, PermutationGroup group) { base.Setup(group, new EquitablePartitionRefiner(GetRefinable(atomContainer))); }
private List <string> GetPlausibleStrategies(Dictionary <PermutationGroup, double[]>[] possibleOutcomesByStrategy) { var plausibleStrategies = m_possibleBallots .SelectToArray(p => Enumerable.Range(0, p.Length).ToHashSet()); bool TrimPossibleStrategies(Func <IEnumerable <double[]>, int[], IEnumerable <int>, IEnumerable <int> > getDominatedStrategies) { bool removedAny = false; for (int i = 0; i < m_possibleBallots.Length; i++) { if (m_possibleBallots[i].Length == 1) { continue; } foreach (var s in getDominatedStrategies(possibleOutcomesByStrategy[i].Values, m_strategyTiebreakers[i], plausibleStrategies[i]).ToList()) { removedAny = true; plausibleStrategies[i].Remove(s); } } if (removedAny) { if (plausibleStrategies.Any(ps => ps.Count == 0)) { throw new InvalidOperationException("There's a bug!"); } for (int i = 0; i < m_possibleBallots.Length; i++) { foreach (var key in possibleOutcomesByStrategy[i].Keys.Where(pg => !pg.IsStillValid(plausibleStrategies)).ToList()) { possibleOutcomesByStrategy[i].Remove(key); } } } return(removedAny); } // Eliminate all strategies which bring no benefit to their employer over a more-preferred strategy // Ignore any strategies which are strictly dominated by another. while (TrimPossibleStrategies((outcomes, tiebreakers, strategies) => from a in strategies from b in strategies where a != b && outcomes.All(outcome => outcome[b] >= outcome[a]) && (tiebreakers[b] < tiebreakers[a] || outcomes.Any(outcome => outcome[b] != outcome[a])) select a)) { ; } // Finally, return all strategies which are part of Nash equilibiria // (where no voter can unilaterally improve the outcome) var plausibleStrategyNames = new HashSet <string>(); var plausibleStrategyLists = plausibleStrategies.SelectToArray(a => a.ToList()); var votersWithMutipleStrategies = Enumerable.Range(0, m_voterCount).Where(i => plausibleStrategies[i].Count > 1).ToList(); foreach (var strategyPermutation in GetAllPermutations(m_voterCount.LengthArray(i => plausibleStrategies[i].Count))) { var ballotPermutation = m_voterCount.LengthArray(i => plausibleStrategyLists[i][strategyPermutation[i]]); var isNashEquilibria = votersWithMutipleStrategies.All(i => { var key = new PermutationGroup(i, ballotPermutation); var outcomes = possibleOutcomesByStrategy[i][key]; var permutationOutcome = outcomes[ballotPermutation[i]]; return(!plausibleStrategyLists[i].Any(o => outcomes[o] > permutationOutcome)); }); if (isNashEquilibria) { for (int i = 0; i < m_voterCount; i++) { if (ballotPermutation[i] > 0) { plausibleStrategyNames.Add(m_strategyNames[i][ballotPermutation[i]]); } } } } return(plausibleStrategyNames.ToList()); }