Exemplo n.º 1
0
def structure_center_type(cgn):
    """Check whether a dicotic game is in the center.

    Parameters
    ----------
    cgn : str
        Dicotic game in combinatorial game notation.

    Returns
    -------
    center_type : {"not_center", "own_inverse", "inv_incomp"}
        The center type determines what kind of game in the center it is:
        * "not_center" : This game is not in the center
        * "own_inverse" : The game is equal to its own inverse and is therefore in the center.
        * "inv_incomp" : The game is incomparable with its own inverse and therefore in the center.
    """
    # Create the game and compute its inverse
    g = Game(cgn)
    h = g.inverse()
    # Check whether this game is it's own inverse
    if str(g) == str(h):
        return "own_inverse"
    # Check whether the game is incomparable with its inverse
    if g.incomparable(h):
        return "inv_incomp"
    # This game is not in the center
    return "not_center"
Exemplo n.º 2
0
def incomparable_pairs(games):
    """Compute incomparable pairs in a list of games.

    Parameters
    ----------
    games : list
        List of games. Each game is represented as str in CGN.

    Returns
    -------
    incomparable_pairs : dict
        Dictionary of sets of str of games.
        Each dictionary item is a set of games that are incomparable
        with the game that is the corresponding key.
    """
    incomparable_pairs = dict()
    # Create keys with empty sets
    for g in games:
        incomparable_pairs[g] = set()

    # Check combinations
    for g, h in combinations(games, r=2):
        if Game(g).incomparable(Game(h)):
            incomparable_pairs[g].add(h)
            incomparable_pairs[h].add(g)

    # Return the dictionary
    return incomparable_pairs
Exemplo n.º 3
0
def filter_unique_canonicals(str_canons):
    str_uniques = []
    for g in str_canons:
        already = False
        for h in str_uniques:
            # Check whether G >= H was checked before
            ggeqh = str_geq_pairs.get((g, h))
            if ggeqh is None:
                # It was not
                ggeqh = Game(g).geq(Game(h))
                str_geq_pairs[(g, h)] = ggeqh

            # If G >= H, it might be that G == H
            if ggeqh:
                # Check whether H >= G was checked before
                hgeqg = str_geq_pairs.get((h, g))
                if hgeqg is None:
                    # It was not
                    hgeqg = Game(h).geq(Game(g))
                    str_geq_pairs[(h, g)] = hgeqg

                # Check whether G == H
                if hgeqg:
                    # Already in list, skip
                    already = True
                    break

        # Was G not already in the list?
        if not already:
            str_uniques.append(g)
            print("Canonical form {:d}:".format(len(str_uniques)), g)

    # Return the set of unique canonical forms
    return str_uniques
Exemplo n.º 4
0
 def test_str(self):
     g = Game()
     self.assertEqual(str(g), "0")
     g.left_options.append(Game())
     self.assertEqual(str(g), "1")
     g.right_options.append(Game())
     self.assertEqual(str(g), "*")
     g.left_options.clear()
     self.assertEqual(str(g), "-1")
Exemplo n.º 5
0
 def test_set_node_cgn(self):
     g = Game()
     num = g._set_node_cgn("{|}", 1)
     self.assertEqual(str(g), "0")
     self.assertEqual(num, 2)
     num = g._set_node_cgn("{|{|}}", 3)
     self.assertEqual(str(g), "0")
     self.assertEqual(num, 4)
     num = g._set_node_cgn("{{|}|{|}}", 1)
     self.assertEqual(str(g), "*")
     self.assertEqual(num, 8)
Exemplo n.º 6
0
def generate_games_from_subsets(subsets: list):
    yield "0"
    for left, right in product(subsets, repeat=2):
        g = Game()
        # Add all options from the sets to the game
        if left:
            g.left_options.extend(Game(opt) for opt in left)
        if right:
            g.right_options.extend(Game(opt) for opt in right)

        # Yield the canonical form as str
        yield str(g.canonical_form())
Exemplo n.º 7
0
def canonical_from_pair(pair: tuple):
    # Split pair in left and right options
    left, right = pair
    g = Game()
    # Add all options from the sets to the game
    if left:
        g.left_options.extend(Game(opt) for opt in left)
    if right:
        g.right_options.extend(Game(opt) for opt in right)

    # Return the canonical form as str
    return str(g.canonical_form())
Exemplo n.º 8
0
def computeCombinations(sets):
    yield "0"
    # Create the cartesian product to create all combinations
    # of Left and Right option sets.
    for leftSet, rightSet in product(sets, repeat=2):
        g = Game()
        # Add all options from the sets to the game
        if leftSet:
            g.leftOptions.extend(Game(opt) for opt in leftSet)
        if rightSet:
            g.rightOptions.extend(Game(opt) for opt in rightSet)

        # Yield the canonical form
        yield str(g.canonicalForm())
Exemplo n.º 9
0
def compute_combinations(sets):
    yield Game("0")
    # Create the cartesian product to create all combinations
    # of Left and Right option sets.
    for left_set, right_set in product(sets, repeat=2):
        g = Game()
        # Add all options from the sets to the game
        if left_set:
            g.left_options.extend(left_set)
        if right_set:
            g.right_options.extend(right_set)

        # Yield the canonical form
        yield g.canonical_form()
Exemplo n.º 10
0
def create_network(canons):
    # Create network
    net = nx.DiGraph()

    # Check all (G, H) pairs
    num_perms = int(len(canons) * (len(canons) - 1))
    perms = permutations(canons, 2)
    for G, H in tqdm(perms, total=num_perms):
        # Check whether G > H
        if Game(G).gtr(Game(H)):
            net.add_edge(G, H)

    # Return the transitive reduction
    red = nx.algorithms.dag.transitive_reduction(net)
    return red.edges
Exemplo n.º 11
0
    def test_get_node_cgn_dot(self):
        dot_str, num = Game()._get_node_cgn_dot("", 0)
        target_str = '\t0[label="0"];\n'
        self.assertEqual(dot_str, target_str)
        self.assertEqual(num, 0)

        dot_str, num = Game("1")._get_node_cgn_dot("abc", 2)
        target_str = 'abc\t2[label="1"];\n\t3[label="0"];\n\t2 -> 3[label="L"];\n'
        self.assertEqual(dot_str, target_str)
        self.assertEqual(num, 3)

        dot_str, num = Game("*2")._get_node_cgn_dot("xyz", -2)
        target_str = 'xyz\t-2[label="*2"];\n\t-1[label="0"];\n\t-2 -> -1[label="L"];\n\t0[label="*"];\n\t1[label="0"];\n\t0 -> 1[label="L"];\n\t2[label="0"];\n\t0 -> 2[label="R"];\n\t-2 -> 0[label="L"];\n\t3[label="0"];\n\t-2 -> 3[label="R"];\n\t4[label="*"];\n\t5[label="0"];\n\t4 -> 5[label="L"];\n\t6[label="0"];\n\t4 -> 6[label="R"];\n\t-2 -> 4[label="R"];\n'
        self.assertEqual(dot_str, target_str)
        self.assertEqual(num, 6)
Exemplo n.º 12
0
def G0(depth: int = 1):
    subsets = [Game("0")]
    for i in range(depth):
        print("Depth is now {:d}.".format(i + 1))

        # Find all subsets
        print("Creating the subset generator.")
        subsets = getAllSubsets(subsets)
        # print('There are {:d} subsets:'.format(len(subsets)), *subsets)

        # Remove sets with dominated options
        print("Filtering the non-dominated subsets.")
        nondomsets = filterDominatedSubsetsPar(subsets)
        print("There are {:d} subsets without any dominated options.".format(len(nondomsets)))

        # Compute the number of games with Left and Right a subset
        print("The number of possible games is {size:d}^2+1={tot:d}.".format(size=len(nondomsets), tot=len(nondomsets) ** 2 + 1))

        # Find all of their canonical forms
        print("Creating the canonical form generator.")
        canons = compute_combinations(nondomsets)

        # Print the canonical forms and add them to a list for the next iteration
        # TODO: Parallelize?
        print("Filtering unique canonical forms.")
        subsets = []
        for g in canons:
            if g not in subsets:
                # Only keep unique canonical forms
                subsets.append(g)
                print("Canonical form {:d}:".format(len(subsets)), g)
Exemplo n.º 13
0
 def test_repr(self):
     g = Game()
     self.assertEqual(g.__repr__(), "0")
     g.left_options.append(Game())
     self.assertEqual(g.__repr__(), "1")
     g.right_options.append(Game())
     self.assertEqual(g.__repr__(), "*")
     g.left_options.clear()
     self.assertEqual(g.__repr__(), "-1")
Exemplo n.º 14
0
 def test_get_cgn(self):
     g = Game()
     self.assertEqual(g.get_cgn(), "0")
     g.left_options.append(Game())
     self.assertEqual(g.get_cgn(), "1")
     g.right_options.append(Game())
     self.assertEqual(g.get_cgn(), "*")
     g.left_options.clear()
     self.assertEqual(g.get_cgn(), "-1")
Exemplo n.º 15
0
    def test_integer_value(self):
        # Check integer games
        self.assertEqual(Game("-3").integer_value(), -3)
        self.assertEqual(Game("-1").integer_value(), -1)
        self.assertEqual(Game("-2").integer_value(), -2)
        self.assertEqual(Game("0").integer_value(), 0)
        self.assertEqual(Game("1").integer_value(), 1)
        self.assertEqual(Game("2").integer_value(), 2)
        self.assertEqual(Game("3").integer_value(), 3)

        # Check ValueError on non-integer games
        with self.assertRaises(ValueError):
            Game("*").integer_value()
        with self.assertRaises(ValueError):
            Game("^").integer_value()
        with self.assertRaises(ValueError):
            Game("v").integer_value()
Exemplo n.º 16
0
def checkSubset(subset_di):
    subset, di = subset_di
    for option_pair in permutations(subset, 2):
        # Check whether this pair was seen before
        outcome = di.get(option_pair)

        if outcome is None:
            # These games were not compared before
            outcome = Game(option_pair[0]).geq(Game(option_pair[1]))
            # Add to dict
            di[option_pair] = outcome

        if outcome:
            # option_pair[0] >= option_pair[1], subset contains dominated options
            return None

    # No dominated options, return this set
    return subset
Exemplo n.º 17
0
def to_canonical_cgn(game):
    """Convert a game to its canoncial form in CGN.

    Parameters
    ----------
    game : str
        The game to convert in combinatorial game notation.
    """
    canonical = str(Game(game).canonical_form())
    return f"{datetime.now():%Y-%m-%d %H:%M:%S};{mp.current_process().name};{game};{canonical}\n"
Exemplo n.º 18
0
    def test_get_cgn_dot(self):
        comp_str = Game().get_cgn_dot()
        target_str = 'digraph Game {\n\t0[label="0"];\n}'
        self.assertEqual(comp_str, target_str)

        comp_str = Game("1").get_cgn_dot()
        target_str = 'digraph Game {\n\t0[label="1"];\n\t1[label="0"];\n\t0 -> 1[label="L"];\n}'
        self.assertEqual(comp_str, target_str)

        comp_str = Game("*").get_cgn_dot()
        target_str = 'digraph Game {\n\t0[label="*"];\n\t1[label="0"];\n\t0 -> 1[label="L"];\n\t2[label="0"];\n\t0 -> 2[label="R"];\n}'
        self.assertEqual(comp_str, target_str)

        comp_str = Game("-1").get_cgn_dot()
        target_str = 'digraph Game {\n\t0[label="-1"];\n\t1[label="0"];\n\t0 -> 1[label="R"];\n}'
        self.assertEqual(comp_str, target_str)

        comp_str = Game("*2").get_cgn_dot()
        target_str = 'digraph Game {\n\t0[label="*2"];\n\t1[label="0"];\n\t0 -> 1[label="L"];\n\t2[label="*"];\n\t3[label="0"];\n\t2 -> 3[label="L"];\n\t4[label="0"];\n\t2 -> 4[label="R"];\n\t0 -> 2[label="L"];\n\t5[label="0"];\n\t0 -> 5[label="R"];\n\t6[label="*"];\n\t7[label="0"];\n\t6 -> 7[label="L"];\n\t8[label="0"];\n\t6 -> 8[label="R"];\n\t0 -> 6[label="R"];\n}'
        self.assertEqual(comp_str, target_str)
Exemplo n.º 19
0
 def test_clear(self):
     g = Game()
     g.left_options.append(Game())
     g.right_options.append(Game())
     g.clear()
     self.assertFalse(g.left_options)
     self.assertFalse(g.right_options)
Exemplo n.º 20
0
    def test_incomparable_zero(self):
        self.assertTrue(Game("*").incomparable_zero())

        self.assertFalse(Game("1").incomparable_zero())
        self.assertFalse(Game("^").incomparable_zero())
        self.assertFalse(Game("0").incomparable_zero())
        self.assertFalse(Game("v").incomparable_zero())
        self.assertFalse(Game("-1").incomparable_zero())
Exemplo n.º 21
0
    def test_equal_zero(self):
        self.assertTrue(Game("0").equal_zero())

        self.assertFalse(Game("1").equal_zero())
        self.assertFalse(Game("^").equal_zero())
        self.assertFalse(Game("*").equal_zero())
        self.assertFalse(Game("v").equal_zero())
        self.assertFalse(Game("-1").equal_zero())
Exemplo n.º 22
0
def to_canonical(games):
    """Convert games to their canoncial forms.

    Parameters
    ----------
    games : iterable
        The games to convert, each in combinatorial game notation.

    Yields
    ------
    canonical : str
        A game in canonical form.

    Notes
    -----
    The order of the converted games is preserverd.
    """
    for g in games:
        yield str(Game(g).canonical_form())
Exemplo n.º 23
0
 def test_incomparable(self):
     self.assertTrue(Game("0").incomparable(Game("*")))
     self.assertTrue(Game("1").incomparable(Game("1") + Game("*")))
     self.assertTrue((Game("1") - Game("1")).incomparable(Game("*")))
     self.assertTrue(Game("*").incomparable(Game("0").inverse()))
Exemplo n.º 24
0
 def test_equal(self):
     self.assertTrue(Game("0").equal(Game("0")))
     self.assertTrue(Game("1").equal(Game("1")))
     self.assertTrue((Game("1") - Game("1")).equal(Game("0")))
     self.assertTrue(Game("*").equal(Game("*").inverse()))
Exemplo n.º 25
0
    def test_outcome_class(self):
        # First player win
        self.assertEqual(Game("*").outcome_class(), "N")
        self.assertEqual(Game("*2").outcome_class(), "N")
        self.assertEqual(Game("{^|v}").outcome_class(), "N")

        # Second player win
        self.assertEqual(Game().outcome_class(), "P")
        self.assertEqual(Game("0").outcome_class(), "P")
        self.assertEqual(Game("{*|*}").outcome_class(), "P")

        # Win for Left
        self.assertEqual(Game("1").outcome_class(), "L")
        self.assertEqual(Game("^").outcome_class(), "L")
        self.assertEqual(Game("{1|^}").outcome_class(), "L")

        # Win for Right
        self.assertEqual(Game("-1").outcome_class(), "R")
        self.assertEqual(Game("v").outcome_class(), "R")
        self.assertEqual(Game("{-1|v}").outcome_class(), "R")
Exemplo n.º 26
0
 def test_set_cgn(self):
     g = Game().set_cgn("0")
     self.assertEqual(str(g), "0")
     with self.assertRaises(ValueError):
         Game().set_cgn("abc")
Exemplo n.º 27
0
    def test_companion(self):
        # First player win
        self.assertEqual(str(Game("*").companion()), "{*|*}")
        self.assertEqual(str(Game("*2").companion()), "{*,{*|*}|*,{*|*}}")
        self.assertEqual(str(Game("{^|v}").companion()),
                         "{{*,0|{*|*}}|{{*|*}|*,0}}")

        # Second player win
        self.assertEqual(str(Game().companion()), "*")
        self.assertEqual(str(Game("0").companion()), "*")
        self.assertEqual(str(Game("{*|*}").companion()), "*")

        # Win for Left
        self.assertEqual(str(Game("1").companion()), "{*,0|}")
        self.assertEqual(str(Game("^").companion()), "{*,0|{*|*}}")
        self.assertEqual(str(Game("{1|^}").companion()),
                         "{0,{*,0|}|{*,0|{*|*}}}")

        # Win for Right
        self.assertEqual(str(Game("-1").companion()), "{|*,0}")
        self.assertEqual(str(Game("v").companion()), "{{*|*}|*,0}")
        self.assertEqual(str(Game("{-1|v}").companion()),
                         "{{|*,0}|0,{{*|*}|*,0}}")
Exemplo n.º 28
0
 def test_canonical_form(self):
     self.assertTrue((Game("*") + Game("*")).canonical_form().equal_zero())
     self.assertEqual(str(Game("{^,*|^,0}").canonical_form()), "^*")
     self.assertEqual(str(Game("^*").canonical_form()), "^*")
     self.assertEqual(str(Game("{2,1,0|-1,-3,2}").canonical_form()),
                      "{{1|}|{|{|-1}}}")
     self.assertEqual(str(Game("*").canonical_form()), "*")
     self.assertEqual(
         str(Game("{{*,0|{*|*}},{*|*}|*,{*|*,{*|*}}}").canonical_form()),
         "{0,^*|*,v}")
     self.assertEqual(
         str(
             Game(
                 "{*2,*3,{0|v*},{^|0,v*}|*,*2,*3,{*,^|0,v*},{0,^*|*,v},{0,^*|0,v*},{^,^*|v,v*}}"
             ).canonical_form()), "{0|*,*2,*3,{0,^*|*,v},{0,^*|0,v*}}")
     self.assertEqual(
         str(
             Game("{*,0,{*,*2,0|*,0},{*,^|v,v*}|*,*2,*3,{*,^|*,v}}").
             canonical_form()), "{0|*,*2,*3}")
     self.assertEqual(
         str(
             Game(
                 "{{*,^|*,0},{0,^*|*,0},{^,^*|0,v*}|*,{0,^*|*,v},{^*|0},{^,^*|v,v*}}"
             ).canonical_form()), "{{*,^|*,0},{0,^*|*,0},{^,^*|0,v*}|0}")
     self.assertEqual(
         str(
             Game(
                 "{{*,*2|0},{*,0|*,*2,0},{^,^*|v,v*}|v,{*,0|*,v},{*,^|v,v*},{^*|v},{^|*,0}}"
             ).canonical_form()), "{{*,*2|0},{*,0|*,*2,0},{^,^*|v,v*}|0}")
     self.assertEqual(
         str(
             Game(
                 "{{*,0|*2,0},{0|v*},{^,^*|*,v}|*2,{0|*,*2},{^,^*|*,*2,0},{^|v*}}"
             ).canonical_form()), "{0|*2,{0|*,*2},{^,^*|*,*2,0},{^|v*}}")
     self.assertEqual(
         str(
             Game(
                 "{{*,0|*,*2,0},{*,0|v},{^*|0}|{*,0|*,v},{*,^|v,v*},{*,v|0},{*2,0|*,0}}"
             ).canonical_form()), "{*,{*,0|*,*2,0},{^*|0}|{*,v|0}}")
     self.assertEqual(
         str(
             Game(
                 "{{*,0|*,*2,0},{*,^|*,v},{0,^*|*,v},{^,^*|0,v*}|0,{*,0|0,^*},{^,^*|*,v}}"
             ).canonical_form()),
         "{{*,0|*,*2,0},{*,^|*,v},{0,^*|*,v},{^,^*|0,v*}|0}")
     self.assertEqual(
         str(
             Game(
                 "{*,0,{*,^|*,0},{0,^*|*,0},{^,^*|*,v}|*,*2,*3,0,{*,^|0,v*},{0,^*|0,v*},{^,^*|*,v}}"
             ).canonical_form()), "{*,0,{*,^|*,0},{0,^*|*,0}|*,*2,*3,0}")
     self.assertEqual(
         str(
             Game("{{*,0|*,v},{*,^|v,v*},{0,^*|0,v*}|{*,v|0},{0,v*|0,v*}}").
             canonical_form()), "{{*,0|*,v},{*,^|v,v*},{0,^*|0,v*}|0}")
     self.assertEqual(
         str(
             Game(
                 "{*,0,{*,^|0,v*},{0,^*|*,0},{^,^*|v,v*}|*,{*,*2,0|*,0},{*,^|*,v},{*,^|0,v*}}"
             ).canonical_form()), "{0|*,{*,*2,0|*,0}}")
     self.assertEqual(
         str(
             Game(
                 "{{*,0|v},{0,^*|*,v},{0|v*},{^,^*|0,v*}|0,{*,0|*,*2,0},{*2,0|0,v*}}"
             ).canonical_form()), "{*,0|*,0,{*,0|*,*2,0}}")
     self.assertEqual(
         str(
             Game(
                 "{*,{*,0|*,*2,0},{0,^*|*,v},{0|v*},{^,^*|0,v*}|*,*2,0,{*,^|*,v},{0,^*|0,v*}}"
             ).canonical_form()), "{*,0,{*,0|*,*2,0}|*,*2,0}")
     self.assertEqual(
         str(
             Game(
                 "{*,*2,{*,*2,0|*,v},{*,^|v,v*},{0,^*|0,v*}|{*,0|v},{0,^*|*,0},{0|*,*2},{^,^*|0,v*}}"
             ).canonical_form()), "0")
     self.assertEqual(
         str(
             Game(
                 "{*2,{*,*2,0|*,v},{*,*2,0|0,v*},{^*|0}|0,{*,*2,0|*,0},{*,^|0,v*},{0,^*|0,v*},{^|*,0}}"
             ).canonical_form()),
         "{*2,{*,*2,0|*,v},{*,*2,0|0,v*},{^*|0}|0}")
     self.assertEqual(
         str(
             Game(
                 "{0,{*,*2,0|0,v*},{*,0|*,*2,0},{*,^|*,v}|{*,0|0,^*},{^,^*|*,*2,0}}"
             ).canonical_form()), "{0|{*,0|0,^*},{^,^*|*,*2,0}}")
     self.assertEqual(
         str(
             Game("{{*,*2|v},{*,0|*,v},{^|0,v*}|*2,{*,*2|0},{^*|v},{^|*,0}}"
                  ).canonical_form()), "{{*,*2|v},{*,0|*,v},{^|0,v*}|0}")
     self.assertEqual(
         str(
             Game("{{*,0|*,*2,0},{^,^*|0,v*}|{*,*2,0|*,0},{^*|v},{^|*,0}}").
             canonical_form()), "{{*,0|*,*2,0},{^,^*|0,v*}|0}")
     self.assertEqual(
         str(
             Game(
                 "{v,{*,*2,0|*,v},{^|0,v*}|*,{*,*2,0|*,v},{*,*2|0},{*,0|0,v*}}"
             ).canonical_form()), "{v,{*,*2,0|*,v},{^|0,v*}|0}")
     self.assertEqual(
         str(
             Game(
                 "{{*,0|0,^*},{0,^*|v,v*}|*,*2,*3,{*,^|*,v},{0,^*|*,v},{0|v*}}"
             ).canonical_form()), "0")
     self.assertEqual(
         str(
             Game(
                 "{*,0,{*,*2,0|0,v*},{*,0|*,*2,0},{0,^*|*,v}|{*,*2,0|*,0},{0|*2}}"
             ).canonical_form()), "{0|{*,*2,0|*,0},{0|*2}}")
Exemplo n.º 29
0
    def test_replace_reversible(self):
        # With return_change = False
        g = Game("{*|*}").replace_reversible()
        self.assertEqual(g, Game("0"))
        g = Game("{^,*|0}").replace_reversible()
        self.assertEqual(g, Game("^*"))

        # With return_change = True
        g, c = Game("{*|*}").replace_reversible(return_change=True)
        self.assertEqual(g, Game("0"))
        self.assertTrue(c)
        g, c = Game("{^,*|0}").replace_reversible(return_change=True)
        self.assertEqual(g, Game("^*"))
        self.assertTrue(c)
        g, c = Game().replace_reversible(return_change=True)
        self.assertEqual(g, Game())
        self.assertFalse(c)
        g, c = Game("*").replace_reversible(return_change=True)
        self.assertEqual(g, Game("*"))
        self.assertFalse(c)
Exemplo n.º 30
0
    def test_remove_dominated(self):
        # With return_change = False
        g = Game("{0,1|0,1}").remove_dominated()
        self.assertEqual(g, Game("{1|0}"))
        g = Game("{*,0|-1,*,1}").remove_dominated()
        self.assertEqual(g, Game("{*,0|-1}"))
        g = Game("{0,*,-1,*|-1,0,-1}").remove_dominated()
        self.assertEqual(g, Game("{*,0|-1}"))

        # With return_change = True
        g, c = Game("{0,1|0,1}").remove_dominated(return_change=True)
        self.assertEqual(g, Game("{1|0}"))
        self.assertTrue(c)
        g, c = Game("{*,0|-1,*,1}").remove_dominated(return_change=True)
        self.assertEqual(g, Game("{*,0|-1}"))
        self.assertTrue(c)
        g, c = Game("{0,*,-1,*|-1,0,-1}").remove_dominated(return_change=True)
        self.assertEqual(g, Game("{*,0|-1}"))
        self.assertTrue(c)
        g, c = Game().remove_dominated(return_change=True)
        self.assertEqual(g, Game())
        self.assertFalse(c)
        g, c = Game("*").remove_dominated(return_change=True)
        self.assertEqual(g, Game("*"))
        self.assertFalse(c)