示例#1
0
def is_package_installed_and_updated(pkg):
    from sage.misc.package import is_package_installed
    try:
        pkginfo = all_packages[pkg]
    except KeyError:
        # Might be an installed old-style package
        condition = is_package_installed(pkg)
    else:
        condition = (pkginfo["installed_version"] == pkginfo["remote_version"])
    return condition
示例#2
0
def OptionalExtension(*args, **kwds):
    """
    If some condition (see INPUT) is satisfied, return an ``Extension``.
    Otherwise, return a ``CythonizeExtension``.

    Typically, the condition is some optional package or something
    depending on the operating system.

    INPUT:

    - ``condition`` -- (boolean) the actual condition

    - ``package`` -- (string) the condition is that this package is
      installed and up-to-date (only used if ``condition`` is not given)

    EXAMPLES::

        sage: from sage_setup.optional_extension import OptionalExtension
        sage: ext = OptionalExtension("foo", ["foo.c"], condition=False)
        sage: print(ext.__class__)
        sage_setup.optional_extension.CythonizeExtension
        sage: ext = OptionalExtension("foo", ["foo.c"], condition=True)
        sage: print(ext.__class__)
        distutils.extension.Extension
        sage: ext = OptionalExtension("foo", ["foo.c"], package="no_such_package")
        sage: print(ext.__class__)
        sage_setup.optional_extension.CythonizeExtension
        sage: ext = OptionalExtension("foo", ["foo.c"], package="pari")
        sage: print(ext.__class__)
        distutils.extension.Extension
    """
    try:
        condition = kwds.pop("condition")
    except KeyError:
        pkg = kwds.pop("package")
        from sage.misc.package import is_package_installed
        try:
            pkginfo = all_packages[pkg]
        except KeyError:
            # Might be an installed old-style package
            condition = is_package_installed(pkg)
        else:
            condition = (
                pkginfo["installed_version"] == pkginfo["remote_version"])

    if condition:
        return Extension(*args, **kwds)
    else:
        return CythonizeExtension(*args, **kwds)
def OptionalExtension(*args, **kwds):
    """
    If some condition (see INPUT) is satisfied, return an ``Extension``.
    Otherwise, return a ``CythonizeExtension``.

    Typically, the condition is some optional package or something
    depending on the operating system.

    INPUT:

    - ``condition`` -- (boolean) the actual condition

    - ``package`` -- (string) the condition is that this package is
      installed and up-to-date (only used if ``condition`` is not given)

    EXAMPLES::

        sage: from sage_setup.optional_extension import OptionalExtension
        sage: ext = OptionalExtension("foo", ["foo.c"], condition=False)
        sage: print(ext.__class__)
        sage_setup.optional_extension.CythonizeExtension
        sage: ext = OptionalExtension("foo", ["foo.c"], condition=True)
        sage: print(ext.__class__)
        distutils.extension.Extension
        sage: ext = OptionalExtension("foo", ["foo.c"], package="no_such_package")
        sage: print(ext.__class__)
        sage_setup.optional_extension.CythonizeExtension
        sage: ext = OptionalExtension("foo", ["foo.c"], package="pari")
        sage: print(ext.__class__)
        distutils.extension.Extension
    """
    try:
        condition = kwds.pop("condition")
    except KeyError:
        pkg = kwds.pop("package")
        from sage.misc.package import is_package_installed
        try:
            pkginfo = all_packages[pkg]
        except KeyError:
            # Might be an installed old-style package
            condition = is_package_installed(pkg)
        else:
            condition = (pkginfo["installed_version"] == pkginfo["remote_version"])

    if condition:
        return Extension(*args, **kwds)
    else:
        return CythonizeExtension(*args, **kwds)
示例#4
0
def QuasiQuadraticResidueCode(p):
    r"""
    A (binary) quasi-quadratic residue code (or QQR code).

    Follows the definition of Proposition 2.2 in [BM]. The code has a generator
    matrix in the block form `G=(Q,N)`. Here `Q` is a `p \times p` circulant
    matrix whose top row is `(0,x_1,...,x_{p-1})`, where `x_i=1` if and only if
    `i` is a quadratic residue `\mod p`, and `N` is a `p \times p` circulant
    matrix whose top row is `(0,y_1,...,y_{p-1})`, where `x_i+y_i=1` for all
    `i`.

    INPUT:

    - ``p`` -- a prime `>2`.

    OUTPUT:

    Returns a QQR code of length `2p`.

    EXAMPLES::

        sage: C = codes.QuasiQuadraticResidueCode(11); C   # optional - gap_packages (Guava package)
        [22, 11] linear code over GF(2)

    These are self-orthogonal in general and self-dual when $p \\equiv 3 \\pmod 4$.

    AUTHOR: David Joyner (11-2005)
    """
    if not is_package_installed('gap_packages'):
        raise PackageNotFoundError('gap_packages')
    F = GF(2)
    gap.load_package("guava")
    gap.eval("C:=QQRCode(" + str(p) + ")")
    gap.eval("G:=GeneratorMat(C)")
    k = int(gap.eval("Length(G)"))
    n = int(gap.eval("Length(G[1])"))
    G = [[
        gfq_gap_to_sage(gap.eval("G[%s][%s]" % (i, j)), F)
        for j in range(1, n + 1)
    ] for i in range(1, k + 1)]
    MS = MatrixSpace(F, k, n)
    return LinearCode(MS(G))
示例#5
0
def RandomLinearCodeGuava(n, k, F):
    r"""
    The method used is to first construct a `k \times n` matrix of the block
    form `(I,A)`, where `I` is a `k \times k` identity matrix and `A` is a
    `k \times (n-k)` matrix constructed using random elements of `F`. Then
    the columns are permuted using a randomly selected element of the symmetric
    group `S_n`.

    INPUT:

    - ``n,k`` -- integers with `n>k>1`.

    OUTPUT:

    Returns a "random" linear code with length `n`, dimension `k` over field `F`.

    EXAMPLES::

        sage: C = codes.RandomLinearCodeGuava(30,15,GF(2)); C      # optional - gap_packages (Guava package)
        [30, 15] linear code over GF(2)
        sage: C = codes.RandomLinearCodeGuava(10,5,GF(4,'a')); C      # optional - gap_packages (Guava package)
        [10, 5] linear code over GF(4)

    AUTHOR: David Joyner (11-2005)
    """
    current_randstate().set_seed_gap()

    q = F.order()
    if not is_package_installed('gap_packages'):
        raise PackageNotFoundError('gap_packages')
    gap.load_package("guava")
    gap.eval("C:=RandomLinearCode(" + str(n) + "," + str(k) + ", GF(" +
             str(q) + "))")
    gap.eval("G:=GeneratorMat(C)")
    k = int(gap.eval("Length(G)"))
    n = int(gap.eval("Length(G[1])"))
    G = [[
        gfq_gap_to_sage(gap.eval("G[%s][%s]" % (i, j)), F)
        for j in range(1, n + 1)
    ] for i in range(1, k + 1)]
    MS = MatrixSpace(F, k, n)
    return LinearCode(MS(G))
示例#6
0
def OptionalExtension(*args, **kwds):
    """
    If some condition (see INPUT) is satisfied, return an ``Extension``.
    Otherwise, return a ``CythonizeExtension``.

    Typically, the condition is some optional package or something
    depending on the operating system.

    INPUT:

    - ``condition`` -- (boolean) the actual condition

    - ``package`` -- (string) the condition is that this package is
      installed (only used if ``condition`` is not given)

    EXAMPLES::

        sage: from sage_setup.optional_extension import OptionalExtension
        sage: ext = OptionalExtension("foo", ["foo.c"], condition=False)
        sage: print ext.__class__
        sage_setup.optional_extension.CythonizeExtension
        sage: ext = OptionalExtension("foo", ["foo.c"], condition=True)
        sage: print ext.__class__
        distutils.extension.Extension
        sage: ext = OptionalExtension("foo", ["foo.c"], package="no_such_package")
        sage: print ext.__class__
        sage_setup.optional_extension.CythonizeExtension
        sage: ext = OptionalExtension("foo", ["foo.c"], package="pari")
        sage: print ext.__class__
        distutils.extension.Extension
    """
    try:
        condition = kwds.pop("condition")
    except KeyError:
        pkg = kwds.pop("package")
        condition = is_package_installed(pkg)

    if condition:
        return Extension(*args, **kwds)
    else:
        return CythonizeExtension(*args, **kwds)
示例#7
0
def OptionalExtension(*args, **kwds):
    """
    If some condition (see INPUT) is satisfied, return an ``Extension``.
    Otherwise, return a ``CythonizeExtension``.

    Typically, the condition is some optional package or something
    depending on the operating system.

    INPUT:

    - ``condition`` -- (boolean) the actual condition

    - ``package`` -- (string) the condition is that this package is
      installed (only used if ``condition`` is not given)

    EXAMPLES::

        sage: from sage_setup.optional_extension import OptionalExtension
        sage: ext = OptionalExtension("foo", ["foo.c"], condition=False)
        sage: print ext.__class__
        sage_setup.optional_extension.CythonizeExtension
        sage: ext = OptionalExtension("foo", ["foo.c"], condition=True)
        sage: print ext.__class__
        distutils.extension.Extension
        sage: ext = OptionalExtension("foo", ["foo.c"], package="no_such_package")
        sage: print ext.__class__
        sage_setup.optional_extension.CythonizeExtension
        sage: ext = OptionalExtension("foo", ["foo.c"], package="pari")
        sage: print ext.__class__
        distutils.extension.Extension
    """
    try:
        condition = kwds.pop("condition")
    except KeyError:
        pkg = kwds.pop("package")
        condition = is_package_installed(pkg)

    if condition:
        return Extension(*args, **kwds)
    else:
        return CythonizeExtension(*args, **kwds)
示例#8
0
def best_linear_code_in_guava(n, k, F):
    r"""
    Returns the linear code of length ``n``, dimension ``k`` over field ``F``
    with the maximal minimum distance which is known to the GAP package GUAVA.

    The function uses the tables described in ``bounds_on_minimum_distance_in_guava`` to
    construct this code. This requires the optional GAP package GUAVA.

    INPUT:

    - ``n`` -- the length of the code to look up

    - ``k`` -- the dimension of the code to look up

    - ``F`` -- the base field of the code to look up


    OUTPUT:

    - A :class:`LinearCode` which is a best linear code of the given parameters known to GUAVA.

    EXAMPLES::

        sage: codes.databases.best_linear_code_in_guava(10,5,GF(2))    # long time; optional - gap_packages (Guava package)
        [10, 5] linear code over GF(2)
        sage: gap.eval("C:=BestKnownLinearCode(10,5,GF(2))")           # long time; optional - gap_packages (Guava package)
        'a linear [10,5,4]2..4 shortened code'

    This means that the best possible binary linear code of length 10 and
    dimension 5 is a code with minimum distance 4 and covering radius s somewhere
    between 2 and 4. Use ``bounds_on_minimum_distance_in_guava(10,5,GF(2))``
    for further details.
    """
    if not is_package_installed('gap_packages'):
        raise PackageNotFoundError('gap_packages')
    gap.load_package("guava")
    q = F.order()
    C = gap("BestKnownLinearCode(%s,%s,GF(%s))" % (n, k, q))
    from .linear_code import LinearCode
    return LinearCode(C.GeneratorMat()._matrix_(F))
示例#9
0
def best_linear_code_in_guava(n, k, F):
    r"""
    Returns the linear code of length ``n``, dimension ``k`` over field ``F``
    with the maximal minimum distance which is known to the GAP package GUAVA.

    The function uses the tables described in ``bounds_on_minimum_distance_in_guava`` to
    construct this code. This requires the optional GAP package GUAVA.

    INPUT:

    - ``n`` -- the length of the code to look up

    - ``k`` -- the dimension of the code to look up

    - ``F`` -- the base field of the code to look up


    OUTPUT:

    - A :class:`LinearCode` which is a best linear code of the given parameters known to GUAVA.

    EXAMPLES::

        sage: codes.databases.best_linear_code_in_guava(10,5,GF(2))    # long time; optional - gap_packages (Guava package)
        [10, 5] linear code over GF(2)
        sage: gap.eval("C:=BestKnownLinearCode(10,5,GF(2))")           # long time; optional - gap_packages (Guava package)
        'a linear [10,5,4]2..4 shortened code'

    This means that the best possible binary linear code of length 10 and
    dimension 5 is a code with minimum distance 4 and covering radius s somewhere
    between 2 and 4. Use ``bounds_on_minimum_distance_in_guava(10,5,GF(2))``
    for further details.
    """
    if not is_package_installed('gap_packages'):
        raise PackageNotFoundError('gap_packages')
    gap.load_package("guava")
    q = F.order()
    C = gap("BestKnownLinearCode(%s,%s,GF(%s))"%(n,k,q))
    from .linear_code import LinearCode
    return LinearCode(C.GeneratorMat()._matrix_(F))
示例#10
0
def QuasiQuadraticResidueCode(p):
    r"""
    A (binary) quasi-quadratic residue code (or QQR code).

    Follows the definition of Proposition 2.2 in [BM]. The code has a generator
    matrix in the block form `G=(Q,N)`. Here `Q` is a `p \times p` circulant
    matrix whose top row is `(0,x_1,...,x_{p-1})`, where `x_i=1` if and only if
    `i` is a quadratic residue `\mod p`, and `N` is a `p \times p` circulant
    matrix whose top row is `(0,y_1,...,y_{p-1})`, where `x_i+y_i=1` for all
    `i`.

    INPUT:

    - ``p`` -- a prime `>2`.

    OUTPUT:

    Returns a QQR code of length `2p`.

    EXAMPLES::

        sage: C = codes.QuasiQuadraticResidueCode(11); C   # optional - gap_packages (Guava package)
        [22, 11] linear code over GF(2)

    These are self-orthogonal in general and self-dual when $p \\equiv 3 \\pmod 4$.

    AUTHOR: David Joyner (11-2005)
    """
    if not is_package_installed('gap_packages'):
        raise PackageNotFoundError('gap_packages')
    F = GF(2)
    gap.load_package("guava")
    gap.eval("C:=QQRCode(" + str(p) + ")")
    gap.eval("G:=GeneratorMat(C)")
    k = int(gap.eval("Length(G)"))
    n = int(gap.eval("Length(G[1])"))
    G = [[gfq_gap_to_sage(gap.eval("G[%s][%s]" % (i, j)), F)
          for j in range(1, n + 1)] for i in range(1, k + 1)]
    MS = MatrixSpace(F, k, n)
    return LinearCode(MS(G))
示例#11
0
def RandomLinearCodeGuava(n, k, F):
    r"""
    The method used is to first construct a `k \times n` matrix of the block
    form `(I,A)`, where `I` is a `k \times k` identity matrix and `A` is a
    `k \times (n-k)` matrix constructed using random elements of `F`. Then
    the columns are permuted using a randomly selected element of the symmetric
    group `S_n`.

    INPUT:

    - ``n,k`` -- integers with `n>k>1`.

    OUTPUT:

    Returns a "random" linear code with length `n`, dimension `k` over field `F`.

    EXAMPLES::

        sage: C = codes.RandomLinearCodeGuava(30,15,GF(2)); C      # optional - gap_packages (Guava package)
        [30, 15] linear code over GF(2)
        sage: C = codes.RandomLinearCodeGuava(10,5,GF(4,'a')); C      # optional - gap_packages (Guava package)
        [10, 5] linear code over GF(4)

    AUTHOR: David Joyner (11-2005)
    """
    current_randstate().set_seed_gap()

    q = F.order()
    if not is_package_installed('gap_packages'):
        raise PackageNotFoundError('gap_packages')
    gap.load_package("guava")
    gap.eval("C:=RandomLinearCode("+str(n)+","+str(k)+", GF("+str(q)+"))")
    gap.eval("G:=GeneratorMat(C)")
    k = int(gap.eval("Length(G)"))
    n = int(gap.eval("Length(G[1])"))
    G = [[gfq_gap_to_sage(gap.eval("G[%s][%s]" % (i, j)), F)
          for j in range(1, n + 1)] for i in range(1, k + 1)]
    MS = MatrixSpace(F, k, n)
    return LinearCode(MS(G))
示例#12
0

if (os.path.isfile(SAGE_INC + "cplex.h") and
    os.path.isfile(os.path.join(SAGE_LOCAL,"lib","libcplex.a"))):
    ext_modules.append(
        Extension("sage.numerical.backends.cplex_backend",
                sources = ["sage/numerical/backends/cplex_backend.pyx"],
                include_dirs = [os.path.join(SAGE_INC,"sage","c_lib","include")],
                language = 'c',
                libraries = ["csage", "stdc++", "cplex"])
        )
else:
    exclude_modules.append('sage/numerical/backends/cplex_backend.pyx')


if is_package_installed('cbc'):
    ext_modules.append(
        Extension("sage.numerical.backends.coin_backend",
                sources = ["sage/numerical/backends/coin_backend.pyx"],
                include_dirs = [os.path.join(SAGE_INC,"sage","c_lib","include")],
                language = 'c++',
                libraries = ["csage", "stdc++", "Cbc", "CbcSolver", "Cgl", "Clp",
                             "CoinUtils", "OsiCbc", "OsiClp", "Osi"])
        )
else:
    exclude_modules.append('sage/numerical/backends/coin_backend.pyx')


# Only include darwin_utilities on OS_X >= 10.5
UNAME = os.uname()
if UNAME[0] == "Darwin" and not UNAME[2].startswith('8.'):
示例#13
0
    def tournaments_nauty(self,
                          n,
                          min_out_degree=None,
                          max_out_degree=None,
                          strongly_connected=False,
                          debug=False,
                          options=""):
        r"""
        Returns all tournaments on `n` vertices using Nauty.

        INPUT:

        - ``n`` (integer) -- number of vertices.

        - ``min_out_degree``, ``max_out_degree`` (integers) -- if set to
          ``None`` (default), then the min/max out-degree is not constrained.

        - ``debug`` (boolean) -- if ``True`` the first line of genbg's output to
          standard error is captured and the first call to the generator's
          ``next()`` function will return this line as a string.  A line leading
          with ">A" indicates a successful initiation of the program with some
          information on the arguments, while a line beginning with ">E"
          indicates an error with the input.

        - ``options`` (string) -- anything else that should be forwarded as
          input to Nauty's genbg. See its documentation for more information :
          `<http://cs.anu.edu.au/~bdm/nauty/>`_.


        .. NOTE::

            To use this method you must first install the Nauty spkg.

        EXAMPLES::

            sage: for g in digraphs.tournaments_nauty(4): # optional - nauty
            ....:    print g.edges(labels = False)        # optional - nauty
            [(1, 0), (2, 0), (2, 1), (3, 0), (3, 1), (3, 2)]
            [(1, 0), (1, 3), (2, 0), (2, 1), (3, 0), (3, 2)]
            [(0, 2), (1, 0), (2, 1), (3, 0), (3, 1), (3, 2)]
            [(0, 2), (0, 3), (1, 0), (2, 1), (3, 1), (3, 2)]
            sage: tournaments = digraphs.tournaments_nauty
            sage: [len(list(tournaments(x))) for x in range(1,8)] # optional - nauty
            [1, 1, 2, 4, 12, 56, 456]
            sage: [len(list(tournaments(x, strongly_connected = True))) for x in range(1,9)] # optional - nauty
            [1, 0, 1, 1, 6, 35, 353, 6008]
        """
        import subprocess
        from sage.misc.package import is_package_installed
        if not is_package_installed("nauty"):
            raise TypeError(
                "The optional nauty spkg does not seem to be installed")

        nauty_input = options

        if min_out_degree is None:
            min_out_degree = 0
        if max_out_degree is None:
            max_out_degree = n - 1

        nauty_input += " -d" + str(min_out_degree)
        nauty_input += " -D" + str(max_out_degree)

        if strongly_connected:
            nauty_input += " -c"

        nauty_input += " " + str(n) + " "

        sp = subprocess.Popen("nauty-gentourng {0}".format(nauty_input),
                              shell=True,
                              stdin=subprocess.PIPE,
                              stdout=subprocess.PIPE,
                              stderr=subprocess.PIPE,
                              close_fds=True)

        if debug:
            yield sp.stderr.readline()

        gen = sp.stdout
        while True:
            try:
                s = gen.next()
            except StopIteration:
                raise StopIteration("Exhausted list of graphs from nauty geng")

            G = DiGraph(n)
            i = 0
            j = 1
            for b in s[:-1]:
                if b == '0':
                    G.add_edge(i, j)
                else:
                    G.add_edge(j, i)

                if j == n - 1:
                    i += 1
                    j = i + 1
                else:
                    j += 1

            yield G
    def nauty(self, number_of_sets, number_of_vertices,
              multiple_sets = False,
              vertex_min_degree = None, vertex_max_degree = None,
              set_max_size = None, set_min_size = None,
              regular = False, uniform = False,
              max_intersection = None,
              connected = False,
              options="", debug=False):
        r"""
        Enumerates hypergraphs up to isomorphism using Nauty.

        INPUT:

        - ``number_of_sets``, ``number_of_vertices`` (integers)

        - ``multiple_sets`` (boolean) -- whether to allow several sets
          of the hypergraph to be equal (set to ``False`` by default).

        - ``vertex_min_degree``, ``vertex_max_degree`` (integers) -- define the
          maximum and minimum degree of an element from the ground set (i.e. the
          number of sets which contain it). Set to ``None`` by default.

        - ``set_min_size``, ``set_max_size`` (integers) -- define the maximum
          and minimum size of a set. Set to ``None`` by default.

        - ``regular`` (integer) -- if set to an integer value `k`, requires the
          hypergraphs to be `k`-regular. It is actually a shortcut for the
          corresponing min/max values.

        - ``uniform`` (integer) -- if set to an integer value `k`, requires the
          hypergraphs to be `k`-uniform. It is actually a shortcut for the
          corresponing min/max values.

        - ``max_intersection`` (integer) -- constraints the maximum cardinality
          of the intersection of two sets fro the hypergraphs. Set to ``None``
          by default.

        - ``connected`` (boolean) -- whether to require the hypergraphs to be
          connected. Set to ``False`` by default.

        - ``debug`` (boolean) -- if ``True`` the first line of genbg's output to
          standard error is captured and the first call to the generator's
          ``next()`` function will return this line as a string.  A line leading
          with ">A" indicates a successful initiation of the program with some
          information on the arguments, while a line beginning with ">E"
          indicates an error with the input.

        - ``options`` (string) -- anything else that should be forwarded as
          input to Nauty's genbg. See its documentation for more information :
          `<http://cs.anu.edu.au/~bdm/nauty/>`_.

          .. NOTE::

              For genbg the *first class* elements are vertices, and *second
              class* elements are the hypergraph's sets.

        OUTPUT:

        A tuple of tuples.

        EXAMPLES:

        Small hypergraphs::

            sage: list(hypergraphs.nauty(4,2)) # optional - nauty
            [((), (0,), (1,), (0, 1))]

        Only connected ones::

            sage: list(hypergraphs.nauty(2,2, connected = True)) # optional - nauty
            [((0,), (0, 1))]

        Non-empty sets only::

            sage: list(hypergraphs.nauty(3,2, set_min_size = 1)) # optional - nauty
            [((0,), (1,), (0, 1))]

        The Fano Plane, as the only 3-uniform hypergraph with 7 sets and 7
        vertices::

            sage: fano = next(hypergraphs.nauty(7, 7, uniform=3, max_intersection=1)) # optional - nauty
            sage: print fano # optional - nauty
            ((0, 1, 2), (0, 3, 4), (0, 5, 6), (1, 3, 5), (2, 4, 5), (2, 3, 6), (1, 4, 6))

        The Fano Plane, as the only 3-regular hypergraph with 7 sets and 7
        vertices::

            sage: fano = next(hypergraphs.nauty(7, 7, regular=3, max_intersection=1)) # optional - nauty
            sage: print fano # optional - nauty
            ((0, 1, 2), (0, 3, 4), (0, 5, 6), (1, 3, 5), (2, 4, 5), (2, 3, 6), (1, 4, 6))
        """
        import subprocess
        from sage.misc.package import is_package_installed
        if not is_package_installed("nauty"):
            raise TypeError("The optional nauty spkg does not seem to be installed")

        nauty_input = options

        if connected:
            nauty_input += " -c"

        if not multiple_sets:
            nauty_input += " -z"

        if not max_intersection is None:
            nauty_input += " -Z"+str(max_intersection)

        # degrees and sizes
        if not regular is False:
            vertex_max_degree = vertex_min_degree = regular
        if vertex_max_degree is None:
            vertex_max_degree = number_of_sets
        if vertex_min_degree is None:
            vertex_min_degree = 0

        if not uniform is False:
            set_max_size = set_min_size = uniform
        if set_max_size is None:
            set_max_size = number_of_vertices
        if set_min_size is None:
            set_min_size = 0

        nauty_input += " -d"+str(vertex_min_degree)+":"+str(set_min_size)
        nauty_input += " -D"+str(vertex_max_degree)+":"+str(set_max_size)


        nauty_input +=  " "+str(number_of_vertices) +" "+str(number_of_sets)+" "

        sp = subprocess.Popen("genbg {0}".format(nauty_input), shell=True,
                              stdin=subprocess.PIPE, stdout=subprocess.PIPE,
                              stderr=subprocess.PIPE, close_fds=True)

        if debug:
            yield sp.stderr.readline()

        gen = sp.stdout
        total = number_of_sets + number_of_vertices
        while True:
            try:
                s = next(gen)
            except StopIteration:
                raise StopIteration("Exhausted list of graphs from nauty geng")

            from sage.graphs.graph import Graph
            G = Graph(s[:-1], format='graph6')

            yield tuple( tuple( x for x in G.neighbors(v)) for v in range(number_of_vertices, total))
示例#15
0
def bounds_on_minimum_distance_in_guava(n, k, F):
    r"""
    Computes a lower and upper bound on the greatest minimum distance of a
    `[n,k]` linear code over the field ``F``.

    This function requires the optional GAP package GUAVA.

    The function returns a GAP record with the two bounds and an explanation for
    each bound. The function Display can be used to show the explanations.

    The values for the lower and upper bound are obtained from a table
    constructed by Cen Tjhai for GUAVA, derived from the table of
    Brouwer. See http://www.codetables.de/ for the most recent data.
    These tables contain lower and upper bounds for `q=2` (when ``n <= 257``),
    `q=3` (when ``n <= 243``), `q=4` (``n <= 256``). (Current as of
    11 May 2006.) For codes over other fields and for larger word lengths,
    trivial bounds are used.

    INPUT:

    - ``n`` -- the length of the code to look up

    - ``k`` -- the dimension of the code to look up

    - ``F`` -- the base field of the code to look up

    OUTPUT:

    - A GAP record object. See below for an example.

    EXAMPLES::

        sage: gap_rec = codes.databases.bounds_on_minimum_distance_in_guava(10,5,GF(2))  # optional - gap_packages (Guava package)
        sage: print(gap_rec)                                                             # optional - gap_packages (Guava package)
        rec(
          construction :=
           [ <Operation "ShortenedCode">,
              [
                  [ <Operation "UUVCode">,
                      [
                          [ <Operation "DualCode">,
                              [ [ <Operation "RepetitionCode">, [ 8, 2 ] ] ] ],
                          [ <Operation "UUVCode">,
                              [
                                  [ <Operation "DualCode">,
                                      [ [ <Operation "RepetitionCode">, [ 4, 2 ] ] ] ]
                                    , [ <Operation "RepetitionCode">, [ 4, 2 ] ] ] ]
                         ] ], [ 1, 2, 3, 4, 5, 6 ] ] ],
          k := 5,
          lowerBound := 4,
          lowerBoundExplanation := ...
          n := 10,
          q := 2,
          references := rec(
               ),
          upperBound := 4,
          upperBoundExplanation := ... )
    """
    if not is_package_installed('gap_packages'):
        raise PackageNotFoundError('gap_packages')
    gap.load_package("guava")
    q = F.order()
    gap.eval("data := BoundsMinimumDistance(%s,%s,GF(%s))"%(n,k,q))
    Ldata = gap.eval("Display(data)")
    return Ldata
示例#16
0
else:
    exclude_modules.append('sage/numerical/backends/gurobi_backend.pyx')

if (os.path.isfile(SAGE_INC + "cplex.h")
        and os.path.isfile(os.path.join(SAGE_LOCAL, "lib", "libcplex.a"))):
    ext_modules.append(
        Extension(
            "sage.numerical.backends.cplex_backend",
            sources=["sage/numerical/backends/cplex_backend.pyx"],
            include_dirs=[os.path.join(SAGE_INC, "sage", "c_lib", "include")],
            language='c',
            libraries=["csage", "stdc++", "cplex"]))
else:
    exclude_modules.append('sage/numerical/backends/cplex_backend.pyx')

if is_package_installed('cbc'):
    ext_modules.append(
        Extension(
            "sage.numerical.backends.coin_backend",
            sources=["sage/numerical/backends/coin_backend.pyx"],
            include_dirs=[os.path.join(SAGE_INC, "sage", "c_lib", "include")],
            language='c++',
            libraries=[
                "csage", "stdc++", "Cbc", "CbcSolver", "Cgl", "Clp",
                "CoinUtils", "OsiCbc", "OsiClp", "Osi"
            ]))
else:
    exclude_modules.append('sage/numerical/backends/coin_backend.pyx')

# Only include darwin_utilities on OS_X >= 10.5
UNAME = os.uname()
示例#17
0
def lovasz_theta(graph):
    r"""
    Return the value of Lovász theta-function of graph

    For a graph `G` this function is denoted by `\theta(G)`, and it can be
    computed in polynomial time. Mathematically, its most important property is the following:

    .. MATH::

        \alpha(G)\leq\theta(G)\leq\chi(\overline{G})

    with `\alpha(G)` and `\chi(\overline{G})` being, respectively, the maximum
    size of an :meth:`independent set <sage.graphs.graph.Graph.independent_set>`
    set of `G` and the :meth:`chromatic number
    <sage.graphs.graph.Graph.chromatic_number>` of the :meth:`complement
    <sage.graphs.generic_graph.GenericGraph.complement>` `\overline{G}` of `G`.

    For more information, see the :wikipedia:`Lovász_number`.

    .. NOTE::

        - Implemented for undirected graphs only. Use to_undirected to convert a
          digraph to an undirected graph.

        - This function requires the optional package ``csdp``, which you can
          install with with ``sage -i csdp``.

    EXAMPLES::

          sage: C=graphs.PetersenGraph()
          sage: C.lovasz_theta()                             # optional csdp
          4.0
          sage: graphs.CycleGraph(5).lovasz_theta()          # optional csdp
          2.236068

    TEST::

        sage: g = Graph()
        sage: g.lovasz_theta() # indirect doctest
        0
    """
    n = graph.order()
    if n == 0:
        return 0

    from networkx import write_edgelist
    from sage.misc.temporary_file import tmp_filename
    import os, subprocess
    from sage.env import SAGE_LOCAL
    from sage.misc.package import is_package_installed, PackageNotFoundError

    if not is_package_installed('csdp'):
        raise PackageNotFoundError("csdp")

    g = graph.relabel(inplace=False, perm=range(1, n + 1)).networkx_graph()
    tf_name = tmp_filename()
    tf = open(tf_name, 'wb')
    tf.write(str(n) + '\n' + str(g.number_of_edges()) + '\n')
    write_edgelist(g, tf, data=False)
    tf.close()
    lines = subprocess.check_output(
        [os.path.join(SAGE_LOCAL, 'bin', 'theta'), tf_name])
    return float(lines.split()[-1])
示例#18
0
def CossidentePenttilaGraph(q):
    r"""
    Cossidente-Penttila `((q^3+1)(q+1)/2,(q^2+1)(q-1)/2,(q-3)/2,(q-1)^2/2)`-strongly regular graph

    For each odd prime power `q`, one can partition the points of the `O_6^-(q)`-generalized
    quadrange `GQ(q,q^2)` into two parts, so that on any of them the induced subgraph of
    the point graph of the GQ has parameters as above [CP05]_.

    Directly follwing the construction in [CP05]_ is not efficient,
    as one then needs to construct the dual `GQ(q^2,q)`. Thus we
    describe here a more efficient approach that we came up with, following a suggestion by
    T.Penttila. Namely, this partition is invariant
    under the subgroup `H=\Omega_3(q^2)<O_6^-(q)`. We build the appropriate `H`, which
    leaves the form `B(X,Y,Z)=XY+Z^2` invariant, and
    pick up two orbits of `H` on the `F_q`-points. One them is `B`-isotropic, and we
    take the representative `(1:0:0)`. The other one corresponds to the points of
    `PG(2,q^2)` that have all the lines on them either missing the conic specified by `B`, or
    intersecting the conic in two points. We take `(1:1:e)` as the representative. It suffices
    to pick `e` so that `e^2+1` is not a square in `F_{q^2}`. Indeed,
    The conic can be viewed as the union of `\{(0:1:0)\}` and `\{(1:-t^2:t) | t \in F_{q^2}\}`.
    The coefficients of a generic line on `(1:1:e)` are `[1:-1-eb:b]`, for `-1\neq eb`.
    Thus, to make sure the intersection with the conic is always even, we need that the
    discriminant of `1+(1+eb)t^2+tb=0` never vanishes, and this is if and only if
    `e^2+1` is not a square. Further, we need to adjust `B`, by multiplying it by appropriately
    chosen `\nu`, so that `(1:1:e)` becomes isotropic under the relative trace norm
    `\nu B(X,Y,Z)+(\nu B(X,Y,Z))^q`. The latter is used then to define the graph.

    INPUT:

    - ``q`` -- an odd prime power.

    EXAMPLES:

    For `q=3` one gets Sims-Gewirtz graph. ::

        sage: G=graphs.CossidentePenttilaGraph(3)    # optional - gap_packages (grape)
        sage: G.is_strongly_regular(parameters=True) # optional - gap_packages (grape)
        (56, 10, 0, 2)

    For `q>3` one gets new graphs. ::

        sage: G=graphs.CossidentePenttilaGraph(5)    # optional - gap_packages (grape)
        sage: G.is_strongly_regular(parameters=True) # optional - gap_packages (grape)
        (378, 52, 1, 8)

    TESTS::

        sage: G=graphs.CossidentePenttilaGraph(7)    # optional - gap_packages (grape) # long time
        sage: G.is_strongly_regular(parameters=True) # optional - gap_packages (grape) # long time
        (1376, 150, 2, 18)
        sage: graphs.CossidentePenttilaGraph(2)
        Traceback (most recent call last):
        ...
        ValueError: q(=2) must be an odd prime power

    REFERENCES:

    .. [CP05] \A.Cossidente and T.Penttila
       Hemisystems on the Hermitian surface
       Journal of London Math. Soc. 72(2005), 731-741
    """
    p, k = is_prime_power(q,get_data=True)
    if k==0 or p==2:
        raise ValueError('q(={}) must be an odd prime power'.format(q))

    from sage.libs.gap.libgap import libgap
    from sage.misc.package import is_package_installed, PackageNotFoundError

    if not is_package_installed('gap_packages'):
        raise PackageNotFoundError('gap_packages')

    adj_list=libgap.function_factory("""function(q)
        local z, e, so, G, nu, G1, G0, B, T, s, O1, O2, x;
        LoadPackage("grape");
        G0:=SO(3,q^2);
        so:=GeneratorsOfGroup(G0);
        G1:=Group(Comm(so[1],so[2]),Comm(so[1],so[3]),Comm(so[2],so[3]));
        B:=InvariantBilinearForm(G0).matrix;
        z:=Z(q^2); e:=z; sqo:=(q^2-1)/2;
        if IsInt(sqo/Order(e^2+z^0)) then
            e:=z^First([2..q^2-2], x-> not IsInt(sqo/Order(z^(2*x)+z^0)));
        fi;
        nu:=z^First([0..q^2-2], x->z^x*(e^2+z^0)+(z^x*(e^2+z^0))^q=0*z);
        T:=function(x)
            local r;
            r:=nu*x*B*x;
            return r+r^q;
        end;
        s:=Group([Z(q)*IdentityMat(3,GF(q))]);
        O1:=Orbit(G1, Set(Orbit(s,z^0*[1,0,0])), OnSets);
        O2:=Orbit(G1, Set(Orbit(s,z^0*[1,1,e])), OnSets);
        G:=Graph(G1,Concatenation(O1,O2),OnSets,
            function(x,y) return x<>y and 0*z=T(x[1]+y[1]); end);
        return List([1..OrderGraph(G)],x->Adjacency(G,x));
        end;""")

    adj = adj_list(q) # for each vertex, we get the list of vertices it is adjacent to
    G = Graph(((i,int(j-1))
               for i,ni in enumerate(adj) for j in ni),
               format='list_of_edges', multiedges=False)
    G.name('CossidentePenttila('+str(q)+')')
    return G
示例#19
0
                if new is not None:
                    self.alias().add(new, store=store, cur=cur)
        else:
            with DBParams(locals(), store, cur):
                return Graph.name(self, new, *largs, **kargs)

    @override.determined(is_bipartite=PlusInfinity(), is_forest=PlusInfinity())
    def odd_girth(self, value, attrs, **kargs):
        inf = value == PlusInfinity()
        if inf:
            del attrs["is_forest"]
        return (not inf, attrs)


AVAILABLE_ALGORITHMS = ["sage"]
if is_package_installed("bliss"):
    AVAILABLE_ALGORITHMS.insert(0, "bliss")


def canonical_label(graph, **kargs):
    r"""
    Return the canonical labeling of ``graph``.

    INPUT:

    - ``graph`` - the graph to compute the canonical labelling for.

    - ``algorithm`` - the algorithm to use to compute the canonical labelling.
      The default value ``None`` means that ``'bliss'`` will be used if
      available, and ``'sage'`` otherwise.
    """
    def solve(self, algorithm='polybori', n=1,  eliminate_linear_variables=True, verbose=False, **kwds):
        r"""
        Find solutions of this boolean polynomial system.

        This function provide a unified interface to several algorithms
        dedicated to solving systems of boolean equations. Depending on
        the particular nature of the system, some might be much faster
        than some others.

        INPUT:

        * ``self`` - a sequence of boolean polynomials

        * ``algorithm`` - the method to use. Possible values are
          ``polybori``, ``sat`` and ``exhaustive_search``. (default:
          ``polybori``, since it is always available)

        * ``n`` - number of solutions to return. If ``n == +Infinity``
          then all solutions are returned. If `n < \infty` then `n`
          solutions are returned if the equations have at least `n`
          solutions. Otherwise, all the solutions are
          returned. (default: ``1``)

        * ``eliminate_linear_variables`` - whether to eliminate
          variables that appear linearly. This reduces the number of
          variables (makes solving faster a priori), but is likely to
          make the equations denser (may make solving slower depending
          on the method).

        * ``verbose`` - whether to display progress and (potentially)
          useful information while the computation runs. (default:
          ``False``)

        EXAMPLES:

        Without argument, a single arbitrary solution is returned::

            sage: R.<x,y,z> = BooleanPolynomialRing()
            sage: S = Sequence([x*y+z, y*z+x, x+y+z+1])
            sage: sol = S.solve(); sol                       # random
            [{y: 1, z: 0, x: 0}]

        We check that it is actually a solution::

            sage: S.subs( sol[0] )
            [0, 0, 0]

        We obtain all solutions::

            sage: sols = S.solve(n=Infinity); sols           # random
            [{x: 0, y: 1, z: 0}, {x: 1, y: 1, z: 1}]
            sage: map( lambda x: S.subs(x), sols)
            [[0, 0, 0], [0, 0, 0]]

        We can force the use of exhaustive search if the optional
        package ``FES`` is present::

            sage: sol = S.solve(algorithm='exhaustive_search'); sol  # random, optional - FES
            [{x: 1, y: 1, z: 1}]
            sage: S.subs( sol[0] )
            [0, 0, 0]

        And we may use SAT-solvers if they are available::

            sage: sol = S.solve(algorithm='sat'); sol                     # random, optional - CryptoMiniSat
            [{y: 1, z: 0, x: 0}]
            sage: S.subs( sol[0] )
            [0, 0, 0]

        TESTS:

        Make sure that variables not occuring in the equations are no problem::

            sage: R.<x,y,z,t> = BooleanPolynomialRing()
            sage: S = Sequence([x*y+z, y*z+x, x+y+z+1])
            sage: sols = S.solve(n=Infinity)
            sage: map( lambda x: S.subs(x), sols)
            [[0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0]]

        Not eliminating linear variables::

            sage: sols = S.solve(n=Infinity, eliminate_linear_variables=False)
            sage: map( lambda x: S.subs(x), sols)
            [[0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0]]

        A tricky case where the linear equations are insatisfiable::

            sage: R.<x,y,z> = BooleanPolynomialRing()
            sage: S = Sequence([x*y*z+x*y+z*y+x*z, x+y+z+1, x+y+z])
            sage: S.solve()
            []

        """
        from sage.rings.polynomial.pbori import BooleanPolynomialRing
        from sage.modules.free_module import VectorSpace

        S = self
        R_origin = R_solving = self.ring()
        reductors = []

        if eliminate_linear_variables:
            T, reductors = self.eliminate_linear_variables(return_reductors=True)
            if T.variables() != ():
                R_solving = BooleanPolynomialRing( T.nvariables(), map(str, list(T.variables())) )
            S = PolynomialSequence( R_solving, [ R_solving(f) for f in T] )

        if S != []:
            if algorithm == "exhaustive_search":
                if not is_package_installed('fes'):
                    raise ValueError('algorithm=exhaustive_search requires the optional library FES. Run "install_package(\'fes\')" to install it.')
                from sage.libs.fes import exhaustive_search
                solutions = exhaustive_search(S, max_sols=n, verbose=verbose, **kwds)

            elif algorithm == "polybori":
                I = S.ideal()
                if verbose:
                    I.groebner_basis(full_prot=True, **kwds)
                else:
                    I.groebner_basis(**kwds)
                solutions = I.variety()
                if len(solutions) >= n:
                    solutions = solutions[:n]

            elif algorithm == "sat":
                from sage.sat.boolean_polynomials import solve as solve_sat
                if verbose:
                    solutions = solve_sat(S, n=n, s_verbosity=1, **kwds)
                else:
                    solutions = solve_sat(S, n=n, **kwds)
            else:
                raise ValueError("unknown 'algorithm' value")
        else:
            solutions = []

        if S.variables() == ():
            solved_variables = set()
        else:
            solved_variables = { R_origin(x).lm() for x in R_solving.gens() }
        eliminated_variables = { f.lex_lead() for f in reductors }
        leftover_variables = { x.lm() for x in R_origin.gens() } - solved_variables - eliminated_variables

        if leftover_variables != set():
            partial_solutions = solutions
            solutions = []
            for sol in partial_solutions:
                for v in VectorSpace( GF(2), len(leftover_variables) ):
                    new_solution = sol.copy()
                    for var,val in zip(leftover_variables, v):
                        new_solution[ var ] = val
                    solutions.append( new_solution )

        for r in reductors:
            for sol in solutions:
                sol[ r.lm() ] = r.subs(sol).constant_coefficient()

        return solutions
示例#21
0
# theme to set a Pygments style, stylesheet, and insert jsMath macros. See
# the directory doc/common/themes/sage/ for files comprising the custom Sage
# theme.
html_theme = 'sage'

# Theme options are theme-specific and customize the look and feel of
# a theme further.  For a list of options available for each theme,
# see the documentation.
html_theme_options = {}

if 'SAGE_DOC_JSMATH' in os.environ:
    from sage.misc.latex_macros import sage_jsmath_macros_easy
    html_theme_options['jsmath_macros'] = sage_jsmath_macros_easy

    from sage.misc.package import is_package_installed
    html_theme_options['jsmath_image_fonts'] = is_package_installed('jsmath-image-fonts')

# Add any paths that contain custom themes here, relative to this directory.
html_theme_path = [os.path.join(SAGE_DOC, 'common/themes')]

# HTML style sheet NOTE: This overrides a HTML theme's corresponding
# setting.
#html_style = 'default.css'

# The name for this set of Sphinx documents.  If None, it defaults to
# "<project> v<release> documentation".
#html_title = None

# A shorter title for the navigation bar.  Default is the same as html_title.
#html_short_title = None
示例#22
0
def structure_description(G, latex=False):
    r"""
    Return a string that tries to describe the structure of ``G``.

    This methods wraps GAP's ``StructureDescription`` method.

    Requires the *optional* ``database_gap`` package.

    For full details, including the form of the returned string and the
    algorithm to build it, see `GAP's documentation
    <http://www.gap-system.org/Manuals/doc/ref/chap39.html>`_.

    INPUT:

    - ``latex`` -- a boolean (default: ``False``). If ``True`` return a
      LaTeX formatted string.

    OUTPUT:

    - string

    .. WARNING::

        From GAP's documentation: The string returned by
        ``StructureDescription`` is **not** an isomorphism invariant:
        non-isomorphic groups can have the same string value, and two
        isomorphic groups in different representations can produce different
        strings.

    EXAMPLES::

        sage: G = CyclicPermutationGroup(6)
        sage: G.structure_description()             # optional - database_gap
        'C6'
        sage: G.structure_description(latex=True)   # optional - database_gap
        'C_{6}'
        sage: G2 = G.direct_product(G, maps=False)
        sage: LatexExpr(G2.structure_description(latex=True))   # optional - database_gap
        C_{6} \times C_{6}

    This method is mainly intended for small groups or groups with few
    normal subgroups. Even then there are some surprises::

        sage: D3 = DihedralGroup(3)
        sage: D3.structure_description()    # optional - database_gap
        'S3'

    We use the Sage notation for the degree of dihedral groups::

        sage: D4 = DihedralGroup(4)
        sage: D4.structure_description()    # optional - database_gap
        'D4'

    Works for finitely presented groups (:trac:`17573`)::

        sage: F.<x, y> = FreeGroup()
        sage: G=F / [x^2*y^-1, x^3*y^2, x*y*x^-1*y^-1]
        sage: G.structure_description()     # optional - database_gap
        'C7'

    And matrix groups (:trac:`17573`)::

        sage: groups.matrix.GL(4,2).structure_description() # optional - database_gap
        'A8'
    """
    import re
    from sage.misc.package import is_package_installed

    def correct_dihedral_degree(match):
        return "%sD%d" % (match.group(1), int(match.group(2)) / 2)

    try:
        description = G._gap_().StructureDescription().__str__()
    except RuntimeError:
        if not is_package_installed('database_gap'):
            raise RuntimeError(
                "You must install the optional database_gap package first.")
        raise

    description = re.sub(r"(\A|\W)D(\d+)", correct_dihedral_degree,
                         description)
    if not latex:
        return description
    description = description.replace("x", r"\times").replace(":", r"\rtimes")
    description = re.sub(r"([A-Za-z]+)([0-9]+)", r"\g<1>_{\g<2>}", description)
    description = re.sub(r"O([+-])", r"O^{\g<1>}", description)

    return description
示例#23
0
def CossidentePenttilaGraph(q):
    r"""
    Cossidente-Penttila `((q^3+1)(q+1)/2,(q^2+1)(q-1)/2,(q-3)/2,(q-1)^2/2)`-strongly regular graph

    For each odd prime power `q`, one can partition the points of the `O_6^-(q)`-generalized
    quadrange `GQ(q,q^2)` into two parts, so that on any of them the induced subgraph of
    the point graph of the GQ has parameters as above [CP05]_.

    Directly follwing the construction in [CP05]_ is not efficient,
    as one then needs to construct the dual `GQ(q^2,q)`. Thus we
    describe here a more efficient approach that we came up with, following a suggestion by
    T.Penttila. Namely, this partition is invariant
    under the subgroup `H=\Omega_3(q^2)<O_6^-(q)`. We build the appropriate `H`, which
    leaves the form `B(X,Y,Z)=XY+Z^2` invariant, and
    pick up two orbits of `H` on the `F_q`-points. One them is `B`-isotropic, and we
    take the representative `(1:0:0)`. The other one corresponds to the points of
    `PG(2,q^2)` that have all the lines on them either missing the conic specified by `B`, or
    intersecting the conic in two points. We take `(1:1:e)` as the representative. It suffices
    to pick `e` so that `e^2+1` is not a square in `F_{q^2}`. Indeed,
    The conic can be viewed as the union of `\{(0:1:0)\}` and `\{(1:-t^2:t) | t \in F_{q^2}\}`.
    The coefficients of a generic line on `(1:1:e)` are `[1:-1-eb:b]`, for `-1\neq eb`.
    Thus, to make sure the intersection with the conic is always even, we need that the
    discriminant of `1+(1+eb)t^2+tb=0` never vanishes, and this is if and only if
    `e^2+1` is not a square. Further, we need to adjust `B`, by multiplying it by appropriately
    chosen `\nu`, so that `(1:1:e)` becomes isotropic under the relative trace norm
    `\nu B(X,Y,Z)+(\nu B(X,Y,Z))^q`. The latter is used then to define the graph.

    INPUT:

    - ``q`` -- an odd prime power.

    EXAMPLES:

    For `q=3` one gets Sims-Gewirtz graph. ::

        sage: G=graphs.CossidentePenttilaGraph(3)    # optional - gap_packages (grape)
        sage: G.is_strongly_regular(parameters=True) # optional - gap_packages (grape)
        (56, 10, 0, 2)

    For `q>3` one gets new graphs. ::

        sage: G=graphs.CossidentePenttilaGraph(5)    # optional - gap_packages (grape)
        sage: G.is_strongly_regular(parameters=True) # optional - gap_packages (grape)
        (378, 52, 1, 8)

    TESTS::

        sage: G=graphs.CossidentePenttilaGraph(7)    # optional - gap_packages (grape) # long time
        sage: G.is_strongly_regular(parameters=True) # optional - gap_packages (grape) # long time
        (1376, 150, 2, 18)
        sage: graphs.CossidentePenttilaGraph(2)
        Traceback (most recent call last):
        ...
        ValueError: q(=2) must be an odd prime power

    REFERENCES:

    .. [CP05] A.Cossidente and T.Penttila
       Hemisystems on the Hermitian surface
       Journal of London Math. Soc. 72(2005), 731-741
    """
    p, k = is_prime_power(q,get_data=True)
    if k==0 or p==2:
        raise ValueError('q(={}) must be an odd prime power'.format(q))

    from sage.libs.gap.libgap import libgap
    from sage.misc.package import is_package_installed, PackageNotFoundError

    if not is_package_installed('gap_packages'):
        raise PackageNotFoundError('gap_packages')

    adj_list=libgap.function_factory("""function(q)
        local z, e, so, G, nu, G1, G0, B, T, s, O1, O2, x;
        LoadPackage("grape");
        G0:=SO(3,q^2);
        so:=GeneratorsOfGroup(G0);
        G1:=Group(Comm(so[1],so[2]),Comm(so[1],so[3]),Comm(so[2],so[3]));
        B:=InvariantBilinearForm(G0).matrix;
        z:=Z(q^2); e:=z; sqo:=(q^2-1)/2;
        if IsInt(sqo/Order(e^2+z^0)) then
            e:=z^First([2..q^2-2], x-> not IsInt(sqo/Order(z^(2*x)+z^0)));
        fi;
        nu:=z^First([0..q^2-2], x->z^x*(e^2+z^0)+(z^x*(e^2+z^0))^q=0*z);
        T:=function(x)
            local r;
            r:=nu*x*B*x;
            return r+r^q;
        end;
        s:=Group([Z(q)*IdentityMat(3,GF(q))]);
        O1:=Orbit(G1, Set(Orbit(s,z^0*[1,0,0])), OnSets);
        O2:=Orbit(G1, Set(Orbit(s,z^0*[1,1,e])), OnSets);
        G:=Graph(G1,Concatenation(O1,O2),OnSets,
            function(x,y) return x<>y and 0*z=T(x[1]+y[1]); end);
        return List([1..OrderGraph(G)],x->Adjacency(G,x));
        end;""")

    adj = adj_list(q) # for each vertex, we get the list of vertices it is adjacent to
    G = Graph(((i,int(j-1))
               for i,ni in enumerate(adj) for j in ni),
               format='list_of_edges', multiedges=False)
    G.name('CossidentePenttila('+str(q)+')')
    return G
示例#24
0
def lovasz_theta(graph):
    r"""
    Return the value of Lovász theta-function of graph

    For a graph `G` this function is denoted by `\theta(G)`, and it can be
    computed in polynomial time. Mathematically, its most important property is the following:

    .. MATH::

        \alpha(G)\leq\theta(G)\leq\chi(\overline{G})

    with `\alpha(G)` and `\chi(\overline{G})` being, respectively, the maximum
    size of an :meth:`independent set <sage.graphs.graph.Graph.independent_set>`
    set of `G` and the :meth:`chromatic number
    <sage.graphs.graph.Graph.chromatic_number>` of the :meth:`complement
    <sage.graphs.generic_graph.GenericGraph.complement>` `\overline{G}` of `G`.

    For more information, see the :wikipedia:`Lovász_number`.

    .. NOTE::

        - Implemented for undirected graphs only. Use to_undirected to convert a
          digraph to an undirected graph.

        - This function requires the optional package ``csdp``, which you can
          install with with ``sage -i csdp``.

    EXAMPLES::

          sage: C=graphs.PetersenGraph()
          sage: C.lovasz_theta()                             # optional csdp
          4.0
          sage: graphs.CycleGraph(5).lovasz_theta()          # optional csdp
          2.236068

    TEST::

        sage: g = Graph()
        sage: g.lovasz_theta() # indirect doctest
        0
    """
    n = graph.order()
    if n == 0:
        return 0

    from networkx import write_edgelist
    from sage.misc.temporary_file import tmp_filename
    import os, subprocess
    from sage.env import SAGE_LOCAL
    from sage.misc.package import is_package_installed, PackageNotFoundError

    if not is_package_installed('csdp'):
        raise PackageNotFoundError("csdp")

    g = graph.relabel(inplace=False, perm=range(1,n+1)).networkx_graph()
    tf_name = tmp_filename()
    tf = open(tf_name, 'wb')
    tf.write(str(n)+'\n'+str(g.number_of_edges())+'\n')
    write_edgelist(g, tf, data=False)
    tf.close()
    lines = subprocess.check_output([os.path.join(SAGE_LOCAL, 'bin', 'theta'), tf_name])
    return float(lines.split()[-1])
示例#25
0
# theme to set a Pygments style, stylesheet, and insert jsMath macros. See
# the directory doc/common/themes/sage/ for files comprising the custom Sage
# theme.
html_theme = 'sage'

# Theme options are theme-specific and customize the look and feel of
# a theme further.  For a list of options available for each theme,
# see the documentation.
html_theme_options = {}

if 'SAGE_DOC_JSMATH' in os.environ:
    from sage.misc.latex_macros import sage_jsmath_macros_easy
    html_theme_options['jsmath_macros'] = sage_jsmath_macros_easy

    from sage.misc.package import is_package_installed
    html_theme_options['jsmath_image_fonts'] = is_package_installed('jsmath-image-fonts')

# Add any paths that contain custom themes here, relative to this directory.
html_theme_path = [os.path.join(SAGE_DOC, 'common/themes')]

# HTML style sheet NOTE: This overrides a HTML theme's corresponding
# setting.
#html_style = 'default.css'

# The name for this set of Sphinx documents.  If None, it defaults to
# "<project> v<release> documentation".
#html_title = None

# A shorter title for the navigation bar.  Default is the same as html_title.
#html_short_title = None
示例#26
0
    def nauty(self,
              number_of_sets,
              number_of_vertices,
              multiple_sets=False,
              vertex_min_degree=None,
              vertex_max_degree=None,
              set_max_size=None,
              set_min_size=None,
              regular=False,
              uniform=False,
              max_intersection=None,
              connected=False,
              options="",
              debug=False):
        r"""
        Enumerates hypergraphs up to isomorphism using Nauty.

        INPUT:

        - ``number_of_sets``, ``number_of_vertices`` (integers)

        - ``multiple_sets`` (boolean) -- whether to allow several sets
          of the hypergraph to be equal (set to ``False`` by default).

        - ``vertex_min_degree``, ``vertex_max_degree`` (integers) -- define the
          maximum and minimum degree of an element from the ground set (i.e. the
          number of sets which contain it). Set to ``None`` by default.

        - ``set_min_size``, ``set_max_size`` (integers) -- define the maximum
          and minimum size of a set. Set to ``None`` by default.

        - ``regular`` (integer) -- if set to an integer value `k`, requires the
          hypergraphs to be `k`-regular. It is actually a shortcut for the
          corresponing min/max values.

        - ``uniform`` (integer) -- if set to an integer value `k`, requires the
          hypergraphs to be `k`-uniform. It is actually a shortcut for the
          corresponing min/max values.

        - ``max_intersection`` (integer) -- constraints the maximum cardinality
          of the intersection of two sets fro the hypergraphs. Set to ``None``
          by default.

        - ``connected`` (boolean) -- whether to require the hypergraphs to be
          connected. Set to ``False`` by default.

        - ``debug`` (boolean) -- if ``True`` the first line of genbg's output to
          standard error is captured and the first call to the generator's
          ``next()`` function will return this line as a string.  A line leading
          with ">A" indicates a successful initiation of the program with some
          information on the arguments, while a line beginning with ">E"
          indicates an error with the input.

        - ``options`` (string) -- anything else that should be forwarded as
          input to Nauty's genbg. See its documentation for more information :
          `<http://cs.anu.edu.au/~bdm/nauty/>`_.

          .. NOTE::

              For genbg the *first class* elements are vertices, and *second
              class* elements are the hypergraph's sets.

        OUTPUT:

        A tuple of tuples.

        EXAMPLES:

        Small hypergraphs::

            sage: list(hypergraphs.nauty(4,2)) # optional - nauty
            [((), (0,), (1,), (0, 1))]

        Only connected ones::

            sage: list(hypergraphs.nauty(2,2, connected = True)) # optional - nauty
            [((0,), (0, 1))]

        Non-empty sets only::

            sage: list(hypergraphs.nauty(3,2, set_min_size = 1)) # optional - nauty
            [((0,), (1,), (0, 1))]

        The Fano Plane, as the only 3-uniform hypergraph with 7 sets and 7
        vertices::

            sage: fano = next(hypergraphs.nauty(7, 7, uniform=3, max_intersection=1)) # optional - nauty
            sage: print fano # optional - nauty
            ((0, 1, 2), (0, 3, 4), (0, 5, 6), (1, 3, 5), (2, 4, 5), (2, 3, 6), (1, 4, 6))

        The Fano Plane, as the only 3-regular hypergraph with 7 sets and 7
        vertices::

            sage: fano = next(hypergraphs.nauty(7, 7, regular=3, max_intersection=1)) # optional - nauty
            sage: print fano # optional - nauty
            ((0, 1, 2), (0, 3, 4), (0, 5, 6), (1, 3, 5), (2, 4, 5), (2, 3, 6), (1, 4, 6))
        """
        import subprocess
        from sage.misc.package import is_package_installed
        if not is_package_installed("nauty"):
            raise TypeError(
                "The optional nauty spkg does not seem to be installed")

        nauty_input = options

        if connected:
            nauty_input += " -c"

        if not multiple_sets:
            nauty_input += " -z"

        if not max_intersection is None:
            nauty_input += " -Z" + str(max_intersection)

        # degrees and sizes
        if not regular is False:
            vertex_max_degree = vertex_min_degree = regular
        if vertex_max_degree is None:
            vertex_max_degree = number_of_sets
        if vertex_min_degree is None:
            vertex_min_degree = 0

        if not uniform is False:
            set_max_size = set_min_size = uniform
        if set_max_size is None:
            set_max_size = number_of_vertices
        if set_min_size is None:
            set_min_size = 0

        nauty_input += " -d" + str(vertex_min_degree) + ":" + str(set_min_size)
        nauty_input += " -D" + str(vertex_max_degree) + ":" + str(set_max_size)

        nauty_input += " " + str(number_of_vertices) + " " + str(
            number_of_sets) + " "

        sp = subprocess.Popen("genbg {0}".format(nauty_input),
                              shell=True,
                              stdin=subprocess.PIPE,
                              stdout=subprocess.PIPE,
                              stderr=subprocess.PIPE,
                              close_fds=True)

        if debug:
            yield sp.stderr.readline()

        gen = sp.stdout
        total = number_of_sets + number_of_vertices
        while True:
            try:
                s = next(gen)
            except StopIteration:
                raise StopIteration("Exhausted list of graphs from nauty geng")

            from sage.graphs.graph import Graph
            G = Graph(s[:-1], format='graph6')

            yield tuple(
                tuple(x for x in G.neighbors(v))
                for v in range(number_of_vertices, total))
示例#27
0
def bounds_on_minimum_distance_in_guava(n, k, F):
    r"""
    Computes a lower and upper bound on the greatest minimum distance of a
    `[n,k]` linear code over the field ``F``.

    This function requires the optional GAP package GUAVA.

    The function returns a GAP record with the two bounds and an explanation for
    each bound. The function Display can be used to show the explanations.

    The values for the lower and upper bound are obtained from a table
    constructed by Cen Tjhai for GUAVA, derived from the table of
    Brouwer. See http://www.codetables.de/ for the most recent data.
    These tables contain lower and upper bounds for `q=2` (when ``n <= 257``),
    `q=3` (when ``n <= 243``), `q=4` (``n <= 256``). (Current as of
    11 May 2006.) For codes over other fields and for larger word lengths,
    trivial bounds are used.

    INPUT:

    - ``n`` -- the length of the code to look up

    - ``k`` -- the dimension of the code to look up

    - ``F`` -- the base field of the code to look up

    OUTPUT:

    - A GAP record object. See below for an example.

    EXAMPLES::

        sage: gap_rec = codes.databases.bounds_on_minimum_distance_in_guava(10,5,GF(2))  # optional - gap_packages (Guava package)
        sage: print(gap_rec)                                                             # optional - gap_packages (Guava package)
        rec(
          construction :=
           [ <Operation "ShortenedCode">,
              [
                  [ <Operation "UUVCode">,
                      [
                          [ <Operation "DualCode">,
                              [ [ <Operation "RepetitionCode">, [ 8, 2 ] ] ] ],
                          [ <Operation "UUVCode">,
                              [
                                  [ <Operation "DualCode">,
                                      [ [ <Operation "RepetitionCode">, [ 4, 2 ] ] ] ]
                                    , [ <Operation "RepetitionCode">, [ 4, 2 ] ] ] ]
                         ] ], [ 1, 2, 3, 4, 5, 6 ] ] ],
          k := 5,
          lowerBound := 4,
          lowerBoundExplanation := ...
          n := 10,
          q := 2,
          references := rec(
               ),
          upperBound := 4,
          upperBoundExplanation := ... )
    """
    if not is_package_installed('gap_packages'):
        raise PackageNotFoundError('gap_packages')
    gap.load_package("guava")
    q = F.order()
    gap.eval("data := BoundsMinimumDistance(%s,%s,GF(%s))" % (n, k, q))
    Ldata = gap.eval("Display(data)")
    return Ldata
示例#28
0
文件: generic.py 项目: drupel/sage
def structure_description(G, latex=False):
    r"""
    Return a string that tries to describe the structure of ``G``.

    This methods wraps GAP's ``StructureDescription`` method.

    Requires the *optional* ``database_gap`` package.

    For full details, including the form of the returned string and the
    algorithm to build it, see `GAP's documentation
    <http://www.gap-system.org/Manuals/doc/ref/chap39.html>`_.

    INPUT:

    - ``latex`` -- a boolean (default: ``False``). If ``True`` return a
      LaTeX formatted string.

    OUTPUT:

    - string

    .. WARNING::

        From GAP's documentation: The string returned by
        ``StructureDescription`` is **not** an isomorphism invariant:
        non-isomorphic groups can have the same string value, and two
        isomorphic groups in different representations can produce different
        strings.

    EXAMPLES::

        sage: G = CyclicPermutationGroup(6)
        sage: G.structure_description()             # optional - database_gap
        'C6'
        sage: G.structure_description(latex=True)   # optional - database_gap
        'C_{6}'
        sage: G2 = G.direct_product(G, maps=False)
        sage: LatexExpr(G2.structure_description(latex=True))   # optional - database_gap
        C_{6} \times C_{6}

    This method is mainly intended for small groups or groups with few
    normal subgroups. Even then there are some surprises::

        sage: D3 = DihedralGroup(3)
        sage: D3.structure_description()    # optional - database_gap
        'S3'

    We use the Sage notation for the degree of dihedral groups::

        sage: D4 = DihedralGroup(4)
        sage: D4.structure_description()    # optional - database_gap
        'D4'

    Works for finitely presented groups (:trac:`17573`)::

        sage: F.<x, y> = FreeGroup()
        sage: G=F / [x^2*y^-1, x^3*y^2, x*y*x^-1*y^-1]
        sage: G.structure_description()     # optional - database_gap
        'C7'

    And matrix groups (:trac:`17573`)::

        sage: groups.matrix.GL(4,2).structure_description() # optional - database_gap
        'A8'
    """
    import re
    from sage.misc.package import is_package_installed
    def correct_dihedral_degree(match):
        return "%sD%d" % (match.group(1), int(match.group(2))/2)

    try:
        description = str(G._gap_().StructureDescription())
    except RuntimeError:
        if not is_package_installed('database_gap'):
            raise RuntimeError("You must install the optional database_gap package first.")
        raise

    description = re.sub(r"(\A|\W)D(\d+)", correct_dihedral_degree, description)
    if not latex:
        return description
    description = description.replace("x", r"\times").replace(":", r"\rtimes")
    description = re.sub(r"([A-Za-z]+)([0-9]+)", r"\g<1>_{\g<2>}", description)
    description = re.sub(r"O([+-])", r"O^{\g<1>}", description)

    return description
示例#29
0
    def tournaments_nauty(self, n,
                          min_out_degree = None, max_out_degree = None,
                          strongly_connected = False, debug=False, options=""):
        r"""
        Returns all tournaments on `n` vertices using Nauty.

        INPUT:

        - ``n`` (integer) -- number of vertices.

        - ``min_out_degree``, ``max_out_degree`` (integers) -- if set to
          ``None`` (default), then the min/max out-degree is not constrained.

        - ``debug`` (boolean) -- if ``True`` the first line of genbg's output to
          standard error is captured and the first call to the generator's
          ``next()`` function will return this line as a string.  A line leading
          with ">A" indicates a successful initiation of the program with some
          information on the arguments, while a line beginning with ">E"
          indicates an error with the input.

        - ``options`` (string) -- anything else that should be forwarded as
          input to Nauty's genbg. See its documentation for more information :
          `<http://cs.anu.edu.au/~bdm/nauty/>`_.


        .. NOTE::

            To use this method you must first install the Nauty spkg.

        EXAMPLES::

            sage: for g in digraphs.tournaments_nauty(4): # optional - nauty
            ....:    print g.edges(labels = False)        # optional - nauty
            [(1, 0), (2, 0), (2, 1), (3, 0), (3, 1), (3, 2)]
            [(1, 0), (1, 3), (2, 0), (2, 1), (3, 0), (3, 2)]
            [(0, 2), (1, 0), (2, 1), (3, 0), (3, 1), (3, 2)]
            [(0, 2), (0, 3), (1, 0), (2, 1), (3, 1), (3, 2)]
            sage: tournaments = digraphs.tournaments_nauty
            sage: [len(list(tournaments(x))) for x in range(1,8)] # optional - nauty
            [1, 1, 2, 4, 12, 56, 456]
            sage: [len(list(tournaments(x, strongly_connected = True))) for x in range(1,9)] # optional - nauty
            [1, 0, 1, 1, 6, 35, 353, 6008]
        """
        import subprocess
        from sage.misc.package import is_package_installed
        if not is_package_installed("nauty"):
            raise TypeError("The optional nauty spkg does not seem to be installed")

        nauty_input = options

        if min_out_degree is None:
            min_out_degree = 0
        if max_out_degree is None:
            max_out_degree = n-1

        nauty_input += " -d"+str(min_out_degree)
        nauty_input += " -D"+str(max_out_degree)

        if strongly_connected:
            nauty_input += " -c"

        nauty_input +=  " "+str(n) +" "

        sp = subprocess.Popen("nauty-gentourng {0}".format(nauty_input), shell=True,
                              stdin=subprocess.PIPE, stdout=subprocess.PIPE,
                              stderr=subprocess.PIPE, close_fds=True)

        if debug:
            yield sp.stderr.readline()

        gen = sp.stdout
        while True:
            try:
                s = gen.next()
            except StopIteration:
                raise StopIteration("Exhausted list of graphs from nauty geng")

            G = DiGraph(n)
            i = 0
            j = 1
            for b in s[:-1]:
                if b == '0':
                    G.add_edge(i,j)
                else:
                    G.add_edge(j,i)

                if j == n-1:
                    i += 1
                    j = i+1
                else:
                    j += 1

            yield G
    def solve(self, algorithm='polybori', n=1,  eliminate_linear_variables=True, verbose=False, **kwds):
        r"""
        Find solutions of this boolean polynomial system.

        This function provide a unified interface to several algorithms
        dedicated to solving systems of boolean equations. Depending on
        the particular nature of the system, some might be much faster
        than some others.

        INPUT:

        * ``self`` - a sequence of boolean polynomials

        * ``algorithm`` - the method to use. Possible values are
          ``polybori``, ``sat`` and ``exhaustive_search``. (default:
          ``polybori``, since it is always available)

        * ``n`` - number of solutions to return. If ``n == +Infinity``
          then all solutions are returned. If `n < \infty` then `n`
          solutions are returned if the equations have at least `n`
          solutions. Otherwise, all the solutions are
          returned. (default: ``1``)

        * ``eliminate_linear_variables`` - whether to eliminate
          variables that appear linearly. This reduces the number of
          variables (makes solving faster a priori), but is likely to
          make the equations denser (may make solving slower depending
          on the method).

        * ``verbose`` - whether to display progress and (potentially)
          useful information while the computation runs. (default:
          ``False``)

        EXAMPLES:

        Without argument, a single arbitrary solution is returned::

            sage: R.<x,y,z> = BooleanPolynomialRing()
            sage: S = Sequence([x*y+z, y*z+x, x+y+z+1])
            sage: sol = S.solve(); sol                       # random
            [{y: 1, z: 0, x: 0}]

        We check that it is actually a solution::

            sage: S.subs( sol[0] )
            [0, 0, 0]

        We obtain all solutions::

            sage: sols = S.solve(n=Infinity); sols           # random
            [{x: 0, y: 1, z: 0}, {x: 1, y: 1, z: 1}]
            sage: map( lambda x: S.subs(x), sols)
            [[0, 0, 0], [0, 0, 0]]

        We can force the use of exhaustive search if the optional
        package ``FES`` is present::

            sage: sol = S.solve(algorithm='exhaustive_search'); sol  # random, optional - FES
            [{x: 1, y: 1, z: 1}]
            sage: S.subs( sol[0] )
            [0, 0, 0]

        And we may use SAT-solvers if they are available::

            sage: sol = S.solve(algorithm='sat'); sol                     # random, optional - CryptoMiniSat
            [{y: 1, z: 0, x: 0}]
            sage: S.subs( sol[0] )
            [0, 0, 0]

        TESTS:

        Make sure that variables not occuring in the equations are no problem::

            sage: R.<x,y,z,t> = BooleanPolynomialRing()
            sage: S = Sequence([x*y+z, y*z+x, x+y+z+1])
            sage: sols = S.solve(n=Infinity)
            sage: map( lambda x: S.subs(x), sols)
            [[0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0]]

        Not eliminating linear variables::

            sage: sols = S.solve(n=Infinity, eliminate_linear_variables=False)
            sage: map( lambda x: S.subs(x), sols)
            [[0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0]]

        A tricky case where the linear equations are insatisfiable::

            sage: R.<x,y,z> = BooleanPolynomialRing()
            sage: S = Sequence([x*y*z+x*y+z*y+x*z, x+y+z+1, x+y+z])
            sage: S.solve()
            []

        """
        from sage.rings.polynomial.pbori import BooleanPolynomialRing
        from sage.modules.free_module import VectorSpace

        S = self
        R_origin = R_solving = self.ring()
        reductors = []

        if eliminate_linear_variables:
            T, reductors = self.eliminate_linear_variables(return_reductors=True)
            if T.variables() != ():
                R_solving = BooleanPolynomialRing( T.nvariables(), map(str, list(T.variables())) )
            S = PolynomialSequence( R_solving, [ R_solving(f) for f in T] )

        if S != []:
            if algorithm == "exhaustive_search":
                if not is_package_installed('fes'):
                    raise ValueError('algorithm=exhaustive_search requires the optional library FES. Run "install_package(\'fes\')" to install it.')
                from sage.libs.fes import exhaustive_search
                solutions = exhaustive_search(S, max_sols=n, verbose=verbose, **kwds)

            elif algorithm == "polybori":
                I = S.ideal()
                if verbose:
                    I.groebner_basis(full_prot=True, **kwds)
                else:
                    I.groebner_basis(**kwds)
                solutions = I.variety()
                if len(solutions) >= n:
                    solutions = solutions[:n]

            elif algorithm == "sat":
                from sage.sat.boolean_polynomials import solve as solve_sat
                if verbose:
                    solutions = solve_sat(S, n=n, s_verbosity=1, **kwds)
                else:
                    solutions = solve_sat(S, n=n, **kwds)
            else:
                raise ValueError("unknown 'algorithm' value")
        else:
            solutions = []

        if S.variables() == ():
            solved_variables = set()
        else:
            solved_variables = { R_origin(x).lm() for x in R_solving.gens() }
        eliminated_variables = { f.lex_lead() for f in reductors }
        leftover_variables = { x.lm() for x in R_origin.gens() } - solved_variables - eliminated_variables

        if leftover_variables != set():
            partial_solutions = solutions
            solutions = []
            for sol in partial_solutions:
                for v in VectorSpace( GF(2), len(leftover_variables) ):
                    new_solution = sol.copy()
                    for var,val in zip(leftover_variables, v):
                        new_solution[ var ] = val
                    solutions.append( new_solution )

        for r in reductors:
            for sol in solutions:
                sol[ r.lm() ] = r.subs(sol).constant_coefficient()

        return solutions
示例#31
0
                                      {self._spec["primary_key"]: self._zooid},
                                      cur = cur)
                update(self._graphprops, "name", new)
        else:
            return Graph.name(self, new, *largs, **kargs)

    @override.determined(is_bipartite = PlusInfinity(),
                         is_forest = PlusInfinity())
    def odd_girth(self, value, attrs, **kargs):
        inf = value == PlusInfinity()
        if inf:
            del attrs["is_forest"]
        return (not inf, attrs)

AVAILABLE_ALGORITHMS = ["sage"]
if is_package_installed("bliss"):
    AVAILABLE_ALGORITHMS.insert(0, "bliss")

def canonical_label(graph, **kargs):
    r"""
    Return the canonical labeling of ``graph``.

    INPUT:

    - ``graph`` - the graph to compute the canonical labelling for.

    - ``algorithm`` - the algorithm to use to compute the canonical labelling.
      The default value ``None`` means that ``'bliss'`` will be used if
      available, and ``'sage'`` otherwise.
    """
    algorithm = lookup(kargs, "algorithm", default = None)