コード例 #1
0
    def is_valid(self):
        """
        Check if the arithmetic matroid axioms are satisfied.
        """
        if not super(ArithmeticMatroidMixin, self).is_valid():
            # check validity of the underlying matroid
            return False

        E = self.groundset()

        # check axioms for arithmetic matroids
        for X in powerset(E):
            X = frozenset(X)
            for v in E:
                if v not in X:
                    if self._is_dependent_from(v, X):
                        # check axiom 1
                        if self.multiplicity(X) % self.multiplicity(X.union([v])) != 0:
                            # print >> sys.stderr, "Axiom 1 fails on", X, v
                            return False

                    else:
                        # check axiom 2
                        if self.multiplicity(X.union([v])) % self.multiplicity(X) != 0:
                            # print >> sys.stderr, "Axiom 2 fails on", X, v
                            return False

        for Y in powerset(E):
            Y = frozenset(Y)

            for X in powerset(Y):
                X = frozenset(X)

                T = []
                F = []

                for y in Y:
                    if y not in X:
                        if self._is_dependent_from(y, X):
                            T.append(y)
                        else:
                            F.append(y)

                if len(F) + self.rank(X) == self.rank(Y):
                    # (X, Y) is a molecule

                    T = frozenset(T)
                    F = frozenset(F)

                    # check axiom 3
                    if self.multiplicity(X) * self.multiplicity(Y) != self.multiplicity(X.union(F)) * self.multiplicity(X.union(T)):
                        return False

                    # check axiom P
                    if (-1)**(len(T)) * sum((-1)**(len(Y)-len(Z)-len(X)) * self.multiplicity(X.union(Z)) for Z in powerset(Y.difference(X))) < 0:
                        return False

        return True
コード例 #2
0
 def is_gcd(self):
     """
     Check if the matroid satisfies the gcd property, defined in [DM13, Section 3].
     """
     return all(
         self.multiplicity(X) == reduce(gcd, (
             self.multiplicity(I) for I in powerset(X)
             if self.rank(X) == self.rank(I) and self.is_independent(I)), 0)
         for X in powerset(self.groundset()))
コード例 #3
0
ファイル: cayley.py プロジェクト: rostam/homsearch
def nonisomorphic_cubes_Z2(n, avoid_complete=False):
    """
  Returns a generator for all n-dimensional Cube-like graphs
  (Cayley graphs over Z_2^n) with their generators.
  With avoid_complete=True avoids the complete graph.
  Iterates over tuples (generatorSet, G).
  """
    vs = VectorSpace(GF(2), n)
    basegens = vs.gens()
    optgens = [v for v in vs if sum(map(int, v)) >= 2]
    total = 2**len(optgens)
    seen_graphs = set()
    c = 0
    for g in powerset(optgens):
        c += 1
        gens = tuple(list(basegens) + g)
        if c % (total / 100 + 1) == 0:
            log.debug("Generating (%d of %d)" % (c, total))
        if avoid_complete:
            if len(g) >= len(optgens):
                continue
        G = CayleyGraph(vs, gens)

        canon = tuple(Graph(G).canonical_label().edges())
        if canon in seen_graphs:
            continue
        log.debug("Unique graph (%d of %d) gens=%s" % (c, total, gens))
        seen_graphs.add(canon)

        yield (gens, G)
コード例 #4
0
    def check_representation(self, A, ordered_groundset=None, check_bases=False):
        """
        Check if the given matrix is a representation for the matroid.
        If check_bases==True, check that the multiplicity is correct only on the bases.
        """
        r = self.full_rank()
        n = len(self.groundset())

        if ordered_groundset is not None:
            # use the groundset in the given order
            E = ordered_groundset
            assert frozenset(E) == self.groundset()
            assert len(E) == len(self.groundset())
        else:
            # to sort the groundset
            E = list(sorted(self.groundset()))

        if A.ncols() != n:
            return False

        for S in powerset(range(n)):
            T = frozenset(E[i] for i in S)   # corresponding subset of E
            if A[:,S].rank() != self.rank(T):
                # print >> sys.stderr, "Not representable, rank of %r is incorrect" % T
                return False

            if check_bases and len(T) != r and self.rank(T) < r:
                # skip multiplicity check
                continue

            if reduce(operator.mul, [d for d in A[:,S].elementary_divisors() if d != 0], 1) != self.multiplicity(T):
                # print >> sys.stderr, "Not representable, multiplicity of %r is incorrect" % T
                return False

        return True
コード例 #5
0
ファイル: cayley.py プロジェクト: gavento/homsearch
def nonisomorphic_cubes_Z2(n, avoid_complete=False):
  """
  Returns a generator for all n-dimensional Cube-like graphs
  (Cayley graphs over Z_2^n) with their generators.
  With avoid_complete=True avoids the complete graph.
  Iterates over tuples (generatorSet, G).
  """
  vs = VectorSpace(GF(2), n)
  basegens = vs.gens()
  optgens = [v for v in vs if sum(map(int,v)) >= 2]
  total = 2**len(optgens)
  seen_graphs = set()
  c = 0
  for g in powerset(optgens):
    c += 1
    gens = tuple(list(basegens) + g)
    if c % (total / 100 + 1) == 0:
      log.debug("Generating (%d of %d)" % (c, total))
    if avoid_complete:
      if len(g) >= len(optgens):
        continue
    G = CayleyGraph(vs, gens)

    canon = tuple(Graph(G).canonical_label().edges())
    if canon in seen_graphs:
      continue
    log.debug("Unique graph (%d of %d) gens=%s" % (c, total, gens))
    seen_graphs.add(canon)

    yield (gens, G)
コード例 #6
0
ファイル: cartan_matrix.py プロジェクト: EnterStudios/sage-1
    def principal_submatrices(self, proper=False):
        """
        Return a list of all principal submatrices of ``self``.

        INPUT:

        - ``proper`` -- if ``True``, return only proper submatrices

        EXAMPLES::

            sage: M = CartanMatrix(['A',2])
            sage: M.principal_submatrices()
            [
                          [ 2 -1]
            [], [2], [2], [-1  2]
            ]
            sage: M.principal_submatrices(proper=True)
            [[], [2], [2]]

        """
        iset = list(range(self.ncols()))
        ret = []
        for l in powerset(iset):
            if not proper or (proper and l != iset):
                ret.append(self.matrix_from_rows_and_columns(l, l))
        return ret
コード例 #7
0
ファイル: cartan_matrix.py プロジェクト: sampadsaha5/sage
    def principal_submatrices(self, proper=False):
        """
        Return a list of all principal submatrices of ``self``.
        
        INPUT:

        - ``proper`` -- if ``True``, return only proper submatrices 
        
        EXAMPLES::

            sage: M = CartanMatrix(['A',2])
            sage: M.principal_submatrices()
            [
                          [ 2 -1]
            [], [2], [2], [-1  2]
            ]
            sage: M.principal_submatrices(proper=True)
            [[], [2], [2]]
            
        """
        iset = range(self.ncols())
        ret = []
        for l in powerset(iset):
            if not proper or (proper and l != iset):
                ret.append(self.matrix_from_rows_and_columns(l, l))
        return ret
コード例 #8
0
 def is_strong_gcd(self):
     """
     Check if the matroid satisfies the gcd property, defined in [PP19, Section 3].
     """
     return all(
         self.multiplicity(X) == reduce(gcd, (
             self.multiplicity(B) for B in self.bases()
             if len(B.intersection(X)) == self.rank(X)), 0)
         for X in powerset(self.groundset()))
コード例 #9
0
 def _is_isomorphism(self, other, morphism):
     """
     Version of is_isomorphism() that does no type checking.
     (see Matroid.is_isomorphism)
     """
     for X in powerset(self.groundset()):
         Y = frozenset(morphism[e] for e in X)
         if self.rank(X) != other.rank(Y) or self.multiplicity(X) != other.multiplicity(Y):
             return False
     return True
コード例 #10
0
ファイル: blob_algebra.py プロジェクト: vojtechsu/sage
    def __iter__(self):
        r"""
        Iterate over ``self``.

        EXAMPLES::

            sage: from sage.combinat.blob_algebra import BlobDiagrams
            sage: BD3 = BlobDiagrams(3)
            sage: sorted(BD3)
            [({}, {{-3, -2}, {-1, 1}, {2, 3}}),
             ({}, {{-3, -2}, {-1, 3}, {1, 2}}),
             ({}, {{-3, 1}, {-2, -1}, {2, 3}}),
             ({}, {{-3, 3}, {-2, -1}, {1, 2}}),
             ({}, {{-3, 3}, {-2, 2}, {-1, 1}}),
             ({{-3, 1}}, {{-2, -1}, {2, 3}}),
             ({{-3, 3}}, {{-2, -1}, {1, 2}}),
             ({{-2, -1}}, {{-3, 1}, {2, 3}}),
             ({{-2, -1}}, {{-3, 3}, {1, 2}}),
             ({{-1, 1}}, {{-3, -2}, {2, 3}}),
             ({{-1, 1}}, {{-3, 3}, {-2, 2}}),
             ({{-1, 3}}, {{-3, -2}, {1, 2}}),
             ({{1, 2}}, {{-3, -2}, {-1, 3}}),
             ({{1, 2}}, {{-3, 3}, {-2, -1}}),
             ({{-3, 1}, {-2, -1}}, {{2, 3}}),
             ({{-3, 3}, {-2, -1}}, {{1, 2}}),
             ({{-3, 3}, {1, 2}}, {{-2, -1}}),
             ({{-2, -1}, {1, 2}}, {{-3, 3}}),
             ({{-1, 3}, {1, 2}}, {{-3, -2}}),
             ({{-3, 3}, {-2, -1}, {1, 2}}, {})]
        """
        for D in DyckWords(self._n):
            markable = set()
            unmarked = []
            unpaired = []
            # Determine the pairing and which pairings are markable
            for i, d in enumerate(D):
                if i >= self._n:
                    i = -2 * self._n + i
                else:
                    i += 1
                if d == 1:
                    unpaired.append(i)
                else:  # d == 0
                    m = unpaired.pop()
                    if not unpaired:
                        markable.add((m, i))
                    else:
                        unmarked.append((m, i))
            for X in powerset(markable):
                yield self.element_class(
                    self, X, unmarked + list(markable.difference(X)))
コード例 #11
0
    def arithmetic_tutte_polynomial(self, x=None, y=None):
        """
        Return the arithmetic Tutte polynomial of the matroid.
        """
        E = self.groundset()
        r = self.full_rank()

        a = x
        b = y
        R = ZZ['x, y']
        x, y = R._first_ngens(2)
        T = R(0)
        for X in powerset(self.groundset()):
            T += self.multiplicity(X) * (x-1) ** (r - self.rank(X)) * (y-1) ** (len(X) - self.rank(X))
        if a is not None and b is not None:
            T = T(a, b)
        return T
コード例 #12
0
def reduced_charges(M):
    """
    Given a snappy manifold M, we find all reduced charges so that:
    (1) no loop in the triangulation passes an odd number of pi's.
    (2) no tetrahedron has three pi's and 
    """
    out = sol_and_kernel(M)
    x, A = out
    nt = M.num_tetrahedra()
    dim = 3 * nt
    V = VectorSpace(ZZ2, dim)
    AA = V.subspace(A)  # the reduced kernel
    xx = V(x)  # the reduced solution

    charges = [xx + sum(B) for B in powerset(AA.basis())]
    charges = [c for c in charges if not has_pi_triple(c)
               ]  # reject if there are three pi's in any tet.
    return charges
コード例 #13
0
ファイル: jones.py プロジェクト: bopopescu/sagelib-1
    def unramified_outside(self, S, d=None, var='a'):
        """
        Return all fields in the database of degree d unramified
        outside S. If d is omitted, return fields of any degree up to 6.
        The fields are ordered by degree and discriminant.

        INPUT:
        
        
        -  ``S`` - list or set of primes, or a single prime
        
        -  ``d`` - None (default, in which case all fields of degree <= 6 are returned) 
           or a positive integer giving the degree of the number fields returned.
        
        -  ``var`` - the name used for the generator of the number fields (default 'a').   
        
        EXAMPLES::
        
            sage: J = JonesDatabase()             # optional - jones_database
            sage: J.unramified_outside([101,109]) # optional - jones_database
            [Number Field in a with defining polynomial x - 1,
             Number Field in a with defining polynomial x^2 - 101,
             Number Field in a with defining polynomial x^2 - 109,
             Number Field in a with defining polynomial x^3 - x^2 - 36*x + 4,
             Number Field in a with defining polynomial x^4 - x^3 + 13*x^2 - 19*x + 361,
             Number Field in a with defining polynomial x^4 - x^3 + 14*x^2 + 34*x + 393,
             Number Field in a with defining polynomial x^5 + 2*x^4 + 7*x^3 + 4*x^2 + 11*x - 6,
             Number Field in a with defining polynomial x^5 + x^4 - 6*x^3 - x^2 + 18*x + 4,
             Number Field in a with defining polynomial x^5 - x^4 - 40*x^3 - 93*x^2 - 21*x + 17]
        """
        try:
            S = list(S)
        except TypeError:
            S = [S]
        Z = []
        for X in powerset(S):
            Z += self.ramified_at(X, d=d, var=var)
        Z = [(k.degree(), k.discriminant().abs(), k.discriminant() > 0, k)
             for k in Z]
        Z.sort()
        return [z[-1] for z in Z]
コード例 #14
0
ファイル: jones.py プロジェクト: bgxcpku/sagelib
    def unramified_outside(self, S, d=None, var='a'):
        """
        Return all fields in the database of degree d unramified
        outside S. If d is omitted, return fields of any degree up to 6.
        The fields are ordered by degree and discriminant.

        INPUT:


        -  ``S`` - list or set of primes, or a single prime

        -  ``d`` - None (default, in which case all fields of degree <= 6 are returned)
           or a positive integer giving the degree of the number fields returned.

        -  ``var`` - the name used for the generator of the number fields (default 'a').

        EXAMPLES::

            sage: J = JonesDatabase()             # optional - database_jones_numfield
            sage: J.unramified_outside([101,109]) # optional - database_jones_numfield
            [Number Field in a with defining polynomial x - 1,
             Number Field in a with defining polynomial x^2 - 101,
             Number Field in a with defining polynomial x^2 - 109,
             Number Field in a with defining polynomial x^3 - x^2 - 36*x + 4,
             Number Field in a with defining polynomial x^4 - x^3 + 13*x^2 - 19*x + 361,
             Number Field in a with defining polynomial x^4 - x^3 + 14*x^2 + 34*x + 393,
             Number Field in a with defining polynomial x^5 + 2*x^4 + 7*x^3 + 4*x^2 + 11*x - 6,
             Number Field in a with defining polynomial x^5 + x^4 - 6*x^3 - x^2 + 18*x + 4,
             Number Field in a with defining polynomial x^5 - x^4 - 40*x^3 - 93*x^2 - 21*x + 17]
        """
        try:
            S = list(S)
        except TypeError:
            S = [S]
        Z = []
        for X in powerset(S):
            Z += self.ramified_at(X, d=d, var=var)
        Z = [(k.degree(), k.discriminant().abs(), k.discriminant() > 0, k) for k in Z]
        Z.sort()
        return [z[-1] for z in Z]
コード例 #15
0
    def shapley_value(self):
        r"""
        Return the Shapley value for ``self``.

        The Shapley value is the "fair" payoff vector and
        is computed by the following formula:

        .. MATH::

            \phi_i(G) = \sum_{S \subseteq \Omega} \sum_{p \in S}
            \frac{1}{|S|\binom{N}{|S|}}
            \bigl( v(S) - v(S \setminus \{p\}) \bigr).

        EXAMPLES:

        A typical example of computing the Shapley value::

            sage: integer_function = {(): 0,
            ....:                  (1,): 6,
            ....:                  (2,): 12,
            ....:                  (3,): 42,
            ....:                  (1, 2,): 12,
            ....:                  (1, 3,): 42,
            ....:                  (2, 3,): 42,
            ....:                  (1, 2, 3,): 42}
            sage: integer_game = CooperativeGame(integer_function)
            sage: integer_game.player_list
            (1, 2, 3)
            sage: integer_game.shapley_value()
            {1: 2, 2: 5, 3: 35}

        A longer example of the Shapley value::

            sage: long_function = {(): 0,
            ....:                  (1,): 0,
            ....:                  (2,): 0,
            ....:                  (3,): 0,
            ....:                  (4,): 0,
            ....:                  (1, 2): 0,
            ....:                  (1, 3): 0,
            ....:                  (1, 4): 0,
            ....:                  (2, 3): 0,
            ....:                  (2, 4): 0,
            ....:                  (3, 4): 0,
            ....:                  (1, 2, 3): 0,
            ....:                  (1, 2, 4): 45,
            ....:                  (1, 3, 4): 40,
            ....:                  (2, 3, 4): 0,
            ....:                  (1, 2, 3, 4): 65}
            sage: long_game = CooperativeGame(long_function)
            sage: long_game.shapley_value()
            {1: 70/3, 2: 10, 3: 25/3, 4: 70/3}
        """
        payoff_vector = {}
        n = Integer(len(self.player_list))
        for player in self.player_list:
            weighted_contribution = 0
            for coalition in powerset(self.player_list):
                if coalition:  # If non-empty
                    k = Integer(len(coalition))
                    weight = 1 / (n.binomial(k) * k)
                    t = tuple(p for p in coalition if p != player)
                    weighted_contribution += weight * (
                        self.ch_f[tuple(coalition)] - self.ch_f[t])
            payoff_vector[player] = weighted_contribution

        return payoff_vector
コード例 #16
0
ファイル: curve_enumerator.py プロジェクト: williamstein/CBH
    def _coeffs_from_height(self, height_tuple):
        """
        Returns a list of tuples of a-invariants of all curves
         described by height_tuple.

        INPUT:

            - ``height_tuple`` -- A tuple of the form
              (H, C, I) such that 
              H: The smallest height >= N
              C: A list of coefficients for curves of this height
              I: A list of indices indicating which of the above coefficients
              achieve this height. The remaining values in C  indicate the 
              max absolute value those coefficients are allowed to obtain
              without altering the height.

              For example, the tuple (4, [1, 2], [1]) for the short Weierstrass
              case denotes set of curves with height 4; these are all of the
              form Y^2 = X^3 + A*X + B, where B=2 and A ranges between -1 and 1.

        OUTPUT:

            - A list of 2-tuples, each consisting of the given height,
              followed by a tuple of a-invariants of a curve of that height.

        EXAMPLES:

            sage: from sage.schemes.elliptic_curves.curve_enumerator import *
            sage: C = CurveEnumerator(family="short_weierstrass")
            sage: B = C.next_height(4); B
            (4, [1, 2], [1])
            sage: L = C._coeffs_from_height(B)
            sage: for ell in L: print ell
            ...: 
            (4, [0, 0, 0, -1, -2])
            (4, [0, 0, 0, -1, 2])
            (4, [0, 0, 0, 0, -2])
            (4, [0, 0, 0, 0, 2])
            (4, [0, 0, 0, 1, -2])
            (4, [0, 0, 0, 1, 2])
        """
        height = height_tuple[0]
        coeffs = height_tuple[1]
        index = height_tuple[2]

        # Produce list of all coefficient tuples with given height
        L = []
        for S in list(powerset(index))[1:]:
            B = []
            for j in range(len(coeffs)):
                if j in S:
                    B.append([-coeffs[j], coeffs[j]])
                elif j in index:
                    B.append(srange(-coeffs[j] + 1, coeffs[j]))
                else:
                    B.append(srange(-coeffs[j], coeffs[j] + 1))
            C = CartesianProduct(*B).list()
            for c in C:
                L.append(c)

        # Convert coefficient tuples to a-invariants
        L2 = []
        for c in L:
            C = self._coeffs_to_a_invariants(c)
            if not self._is_singular(C):
                L2.append((height, C))
        return L2
コード例 #17
0
    def __init__(self, characteristic_function):
        r"""
        Initializes a co-operative game and checks the inputs.

        TESTS:

        An attempt to construct a game from an integer::

            sage: int_game = CooperativeGame(4)
            Traceback (most recent call last):
            ...
            TypeError: characteristic function must be a dictionary

        This test checks that an incorrectly entered singularly tuple will be
        changed into a tuple. In this case ``(1)`` becomes ``(1,)``::

            sage: tuple_function = {(): 0,
            ....:                  (1): 6,
            ....:                  (2,): 12,
            ....:                  (3,): 42,
            ....:                  (1, 2,): 12,
            ....:                  (1, 3,): 42,
            ....:                  (2, 3,): 42,
            ....:                  (1, 2, 3,): 42}
            sage: tuple_game = CooperativeGame(tuple_function)

        This test checks that if a key is not a tuple an error is raised::

            sage: error_function = {(): 0,
            ....:                  (1,): 6,
            ....:                  (2,): 12,
            ....:                  (3,): 42,
            ....:                  12: 12,
            ....:                  (1, 3,): 42,
            ....:                  (2, 3,): 42,
            ....:                  (1, 2, 3,): 42}
            sage: error_game = CooperativeGame(error_function)
            Traceback (most recent call last):
            ...
            TypeError: key must be a tuple

        A test to ensure that the characteristic function is the power
        set of the grand coalition (ie all possible sub-coalitions)::

            sage: incorrect_function = {(): 0,
            ....:                  (1,): 6,
            ....:                  (2,): 12,
            ....:                  (3,): 42,
            ....:                  (1, 2, 3,): 42}
            sage: incorrect_game = CooperativeGame(incorrect_function)
            Traceback (most recent call last):
            ...
            ValueError: characteristic function must be the power set
        """
        if not isinstance(characteristic_function, dict):
            raise TypeError("characteristic function must be a dictionary")

        self.ch_f = characteristic_function
        for key in list(self.ch_f):
            if len(str(key)) == 1 and not isinstance(key, tuple):
                self.ch_f[(key, )] = self.ch_f.pop(key)
            elif not isinstance(key, tuple):
                raise TypeError("key must be a tuple")

        for key in list(self.ch_f):
            sortedkey = tuple(sorted(key))
            self.ch_f[sortedkey] = self.ch_f.pop(key)

        self.player_list = max(characteristic_function, key=len)
        for coalition in powerset(self.player_list):
            if tuple(sorted(coalition)) not in self.ch_f:
                raise ValueError(
                    "characteristic function must be the power set")

        self.number_players = len(self.player_list)
コード例 #18
0
ファイル: curve_enumerator.py プロジェクト: williamstein/CBH
    def _coeffs_from_height(self,height_tuple):
        """
        Returns a list of tuples of a-invariants of all curves
         described by height_tuple.

        INPUT:

            - ``height_tuple`` -- A tuple of the form
              (H, C, I) such that 
              H: The smallest height >= N
              C: A list of coefficients for curves of this height
              I: A list of indices indicating which of the above coefficients
              achieve this height. The remaining values in C  indicate the 
              max absolute value those coefficients are allowed to obtain
              without altering the height.

              For example, the tuple (4, [1, 2], [1]) for the short Weierstrass
              case denotes set of curves with height 4; these are all of the
              form Y^2 = X^3 + A*X + B, where B=2 and A ranges between -1 and 1.

        OUTPUT:

            - A list of 2-tuples, each consisting of the given height,
              followed by a tuple of a-invariants of a curve of that height.

        EXAMPLES:

            sage: from sage.schemes.elliptic_curves.curve_enumerator import *
            sage: C = CurveEnumerator(family="short_weierstrass")
            sage: B = C.next_height(4); B
            (4, [1, 2], [1])
            sage: L = C._coeffs_from_height(B)
            sage: for ell in L: print ell
            ...: 
            (4, [0, 0, 0, -1, -2])
            (4, [0, 0, 0, -1, 2])
            (4, [0, 0, 0, 0, -2])
            (4, [0, 0, 0, 0, 2])
            (4, [0, 0, 0, 1, -2])
            (4, [0, 0, 0, 1, 2])
        """
        height = height_tuple[0]
        coeffs = height_tuple[1]
        index  = height_tuple[2]

        # Produce list of all coefficient tuples with given height
        L = []
        for S in list(powerset(index))[1:]:
            B = []
            for j in range(len(coeffs)):
                if j in S:
                    B.append([-coeffs[j],coeffs[j]])
                elif j in index:
                    B.append(srange(-coeffs[j]+1,coeffs[j]))
                else:
                    B.append(srange(-coeffs[j],coeffs[j]+1))
            C = CartesianProduct(*B).list()
            for c in C:
                L.append(c)

        # Convert coefficient tuples to a-invariants
        L2 = []
        for c in L:
            C = self._coeffs_to_a_invariants(c)
            if not self._is_singular(C):
                L2.append((height,C))
        return L2
コード例 #19
0
ファイル: cooperative_game.py プロジェクト: mcognetta/sage
    def shapley_value(self):
        r"""
        Return the Shapley value for ``self``.

        The Shapley value is the "fair" payoff vector and
        is computed by the following formula:

        .. MATH::

            \phi_i(G) = \sum_{S \subseteq \Omega} \sum_{p \in S}
            \frac{1}{|S|\binom{N}{|S|}}
            \bigl( v(S) - v(S \setminus \{p\}) \bigr).

        EXAMPLES:

        A typical example of computing the Shapley value::

            sage: integer_function = {(): 0,
            ....:                  (1,): 6,
            ....:                  (2,): 12,
            ....:                  (3,): 42,
            ....:                  (1, 2,): 12,
            ....:                  (1, 3,): 42,
            ....:                  (2, 3,): 42,
            ....:                  (1, 2, 3,): 42}
            sage: integer_game = CooperativeGame(integer_function)
            sage: integer_game.player_list
            (1, 2, 3)
            sage: integer_game.shapley_value()
            {1: 2, 2: 5, 3: 35}

        A longer example of the Shapley value::

            sage: long_function = {(): 0,
            ....:                  (1,): 0,
            ....:                  (2,): 0,
            ....:                  (3,): 0,
            ....:                  (4,): 0,
            ....:                  (1, 2): 0,
            ....:                  (1, 3): 0,
            ....:                  (1, 4): 0,
            ....:                  (2, 3): 0,
            ....:                  (2, 4): 0,
            ....:                  (3, 4): 0,
            ....:                  (1, 2, 3): 0,
            ....:                  (1, 2, 4): 45,
            ....:                  (1, 3, 4): 40,
            ....:                  (2, 3, 4): 0,
            ....:                  (1, 2, 3, 4): 65}
            sage: long_game = CooperativeGame(long_function)
            sage: long_game.shapley_value()
            {1: 70/3, 2: 10, 3: 25/3, 4: 70/3}
        """
        payoff_vector = {}
        n = Integer(len(self.player_list))
        for player in self.player_list:
            weighted_contribution = 0
            for coalition in powerset(self.player_list):
                if coalition:  # If non-empty
                    k = Integer(len(coalition))
                    weight = 1 / (n.binomial(k) * k)
                    t = tuple(p for p in coalition if p != player)
                    weighted_contribution += weight * (self.ch_f[tuple(coalition)]
                                                       - self.ch_f[t])
            payoff_vector[player] = weighted_contribution

        return payoff_vector
コード例 #20
0
ファイル: cooperative_game.py プロジェクト: mcognetta/sage
    def __init__(self, characteristic_function):
        r"""
        Initializes a co-operative game and checks the inputs.

        TESTS:

        An attempt to construct a game from an integer::

            sage: int_game = CooperativeGame(4)
            Traceback (most recent call last):
            ...
            TypeError: characteristic function must be a dictionary

        This test checks that an incorrectly entered singularly tuple will be
        changed into a tuple. In this case ``(1)`` becomes ``(1,)``::

            sage: tuple_function = {(): 0,
            ....:                  (1): 6,
            ....:                  (2,): 12,
            ....:                  (3,): 42,
            ....:                  (1, 2,): 12,
            ....:                  (1, 3,): 42,
            ....:                  (2, 3,): 42,
            ....:                  (1, 2, 3,): 42}
            sage: tuple_game = CooperativeGame(tuple_function)

        This test checks that if a key is not a tuple an error is raised::

            sage: error_function = {(): 0,
            ....:                  (1,): 6,
            ....:                  (2,): 12,
            ....:                  (3,): 42,
            ....:                  12: 12,
            ....:                  (1, 3,): 42,
            ....:                  (2, 3,): 42,
            ....:                  (1, 2, 3,): 42}
            sage: error_game = CooperativeGame(error_function)
            Traceback (most recent call last):
            ...
            TypeError: key must be a tuple

        A test to ensure that the characteristic function is the power
        set of the grand coalition (ie all possible sub-coalitions)::

            sage: incorrect_function = {(): 0,
            ....:                  (1,): 6,
            ....:                  (2,): 12,
            ....:                  (3,): 42,
            ....:                  (1, 2, 3,): 42}
            sage: incorrect_game = CooperativeGame(incorrect_function)
            Traceback (most recent call last):
            ...
            ValueError: characteristic function must be the power set
        """
        if type(characteristic_function) is not dict:
            raise TypeError("characteristic function must be a dictionary")

        self.ch_f = characteristic_function
        for key in self.ch_f:
            if len(str(key)) == 1 and type(key) is not tuple:
                self.ch_f[(key,)] = self.ch_f.pop(key)
            elif type(key) is not tuple:
                raise TypeError("key must be a tuple")
        for key in self.ch_f:
            sortedkey = tuple(sorted(list(key)))
            self.ch_f[sortedkey] = self.ch_f.pop(key)

        self.player_list = max(characteristic_function.keys(), key=lambda key: len(key))
        for coalition in powerset(self.player_list):
            if tuple(sorted(list(coalition))) not in sorted(self.ch_f.keys()):
                raise ValueError("characteristic function must be the power set")

        self.number_players = len(self.player_list)
コード例 #21
0
    def poset_of_layers(self):
        """
        Compute the poset of layers of the associated toric arrangement, using Lenz's algorithm [Len17a].
        """
        # TODO: implement for Q != 0
        if self._Q.ncols() > 0:
            raise NotImplementedError


        A = self._A.transpose()
        E = range(A.nrows())

        data = {}

        # compute Smith normal forms of all submatrices
        for S in powerset(E):
            D, U, V = A[S,:].smith_form()   # D == U*A[S,:]*V
            diagonal = [D[i,i] if i < D.ncols() else 0 for i in xrange(len(S))]
            data[tuple(S)] = (diagonal, U)

        # generate al possible elements of the poset of layers
        elements = {tuple(S): list(vector(ZZ, x) for x in itertools.product(*(range(max(data[tuple(S)][0][i], 1)) for i in xrange(len(S))))) for S in powerset(E)}

        for l in elements.itervalues():
            for v in l:
                v.set_immutable()

        possible_layers = list((S, x) for (S, l) in elements.iteritems() for x in l)
        uf = DisjointSet(possible_layers)

        cover_relations = []

        for (S, l) in elements.iteritems():
            diagonal_S, U_S = data[S]
            rk_S = A[S,:].rank()

            for s in S:
                i = S.index(s)  # index where the element s appears in S
                T = tuple(t for t in S if t != s)

                diagonal_T, U_T = data[T]
                rk_T = A[T,:].rank()

                for x in l:
                    h = (S, x)

                    y = U_S**(-1) * x
                    z = U_T * vector(ZZ, y[:i].list() + y[i+1:].list())
                    w = vector(ZZ, (a % diagonal_T[j] if diagonal_T[j] > 0 else 0 for j, a in enumerate(z)))
                    w.set_immutable()

                    ph = (T, w)

                    if rk_S == rk_T:
                        uf.union(h, ph)

                    else:
                        cover_relations.append((ph, h))

        # find representatives for layers (we keep the representative (S,x) with maximal S)
        root_to_representative_dict = {}
        for root, subset in uf.root_to_elements_dict().iteritems():
            S, x = max(subset, key=lambda (S, x): len(S))
            S_labeled = tuple(self._E[i] for i in S)
            root_to_representative_dict[root] = (S_labeled, x)

        # get layers and cover relations
        layers = root_to_representative_dict.values()
        cover_relations = set(
            (root_to_representative_dict[uf.find(a)], root_to_representative_dict[uf.find(b)])
            for (a,b) in cover_relations)

        return Poset(data=(layers, cover_relations), cover_relations=True)