Beispiel #1
0
    def __init__(self, verbosity=0, confl_limit=None, threads=None):
        r"""
        Constuct a new CryptoMiniSat instance.

        See the documentation class for the description of inputs.

        EXAMPLES::

            sage: from sage.sat.solvers.cryptominisat import CryptoMiniSat
            sage: solver = CryptoMiniSat(threads=1)                     # optional - cryptominisat
        """
        if threads is None:
            from sage.parallel.ncpus import ncpus
            threads = ncpus()
        if confl_limit is None:
            from sys import maxint
            confl_limit = maxint
        try:
            from pycryptosat import Solver
        except ImportError:
            from sage.misc.package import PackageNotFoundError
            raise PackageNotFoundError("cryptominisat")
        self._solver = Solver(verbose=int(verbosity), confl_limit=int(confl_limit), threads=int(threads))
        self._nvars = 0
        self._clauses = []
Beispiel #2
0
 def _start(self):
     try:
         Expect._start(self)
     except RuntimeError:
         from sage.misc.package import PackageNotFoundError
         raise PackageNotFoundError("kash")
     # Turn off the annoying timer.
     self.eval('Time(false);')
Beispiel #3
0
 def _start(self):
     try:
         Expect._start(self)
     except RuntimeError:
         # TODO: replace this error with something more accurate.
         from sage.misc.package import PackageNotFoundError
         raise PackageNotFoundError("kash")
     # Turn off the annoying timer.
     self.eval('Time(false);')
Beispiel #4
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))
Beispiel #5
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))
Beispiel #6
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))
Beispiel #7
0
    def get(self, S, var='a'):
        """
        Return all fields in the database ramified exactly at
        the primes in S.

        INPUT:

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

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

        EXAMPLES::

            sage: J = JonesDatabase()              # optional - database_jones_numfield
            sage: J.get(163, var='z')              # optional - database_jones_numfield
            [Number Field in z with defining polynomial x^2 + 163,
             Number Field in z with defining polynomial x^3 - x^2 - 54*x + 169,
             Number Field in z with defining polynomial x^4 - x^3 - 7*x^2 + 2*x + 9]
            sage: J.get([3, 4])                    # optional - database_jones_numfield
            Traceback (most recent call last):
            ...
            ValueError: S must be a list of primes
        """
        if self.root is None:
            if os.path.exists(JONESDATA + "/jones.sobj"):
                self.root = load(JONESDATA + "/jones.sobj")
            else:
                raise PackageNotFoundError("database_jones_numfield")
        try:
            S = list(S)
        except TypeError:
            S = [S]
        if not all([p.is_prime() for p in S]):
            raise ValueError("S must be a list of primes")
        S.sort()
        s = tuple(S)
        if s not in self.root:
            return []
        return [NumberField(f, var, check=False) for f in self.root[s]]
Beispiel #8
0
    def __init__(self, verbosity=0, prop_limit=0):
        r"""
        Constuct a new PicoSAT instance.

        See the documentation class for the description of inputs.

        EXAMPLES::

            sage: from sage.sat.solvers.picosat import PicoSAT
            sage: solver = PicoSAT()                       # optional - pycosat
        """
        self._verbosity = int(verbosity)
        if prop_limit is None:
            self._prop_limit = 0
        else:
            self._prop_limit = int(prop_limit)
        try:
            import pycosat
        except ImportError:
            from sage.misc.package import PackageNotFoundError
            raise PackageNotFoundError("pycosat")
        self._solve = pycosat.solve
        self._nvars = 0
        self._clauses = []
Beispiel #9
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])
Beispiel #10
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
Beispiel #11
0
    def ehrhart_polynomial(self,
                           verbose=False,
                           dual=None,
                           irrational_primal=None,
                           irrational_all_primal=None,
                           maxdet=None,
                           no_decomposition=None,
                           compute_vertex_cones=None,
                           smith_form=None,
                           dualization=None,
                           triangulation=None,
                           triangulation_max_height=None,
                           **kwds):
        r"""
        Return the Ehrhart polynomial of this polyhedron.

        Let `P` be a lattice polytope in `\RR^d` and define `L(P,t) = \# (tP
        \cap \ZZ^d)`. Then E. Ehrhart proved in 1962 that `L` coincides with a
        rational polynomial of degree `d` for integer `t`. `L` is called the
        *Ehrhart polynomial* of `P`. For more information see the
        :wikipedia:`Ehrhart_polynomial`.

        INPUT:

        - ``verbose`` - (boolean, default to ``False``) if ``True``, print the
          whole output of the LattE command.

        The following options are passed to the LattE command, for details you
        should consult `the LattE documentation
        <https://www.math.ucdavis.edu/~latte/software/packages/latte_current/>`__:

        - ``dual`` - (boolean) triangulate and signed-decompose in the dual
          space

        - ``irrational_primal`` - (boolean) triangulate in the dual space,
          signed-decompose in the primal space using irrationalization.

        - ``irrational_all_primal`` - (boolean) Triangulate and signed-decompose
          in the primal space using irrationalization.

        - ``maxdet`` -- (integer) decompose down to an index (determinant) of
          ``maxdet`` instead of index 1 (unimodular cones).

        - ``no_decomposition`` -- (boolean) do not signed-decompose simplicial cones.

        - ``compute_vertex_cones`` -- (string) either 'cdd' or 'lrs' or '4ti2'

        - ``smith_form`` -- (string) either 'ilio' or 'lidia'

        - ``dualization`` -- (string) either 'cdd' or '4ti2'

        - ``triangulation`` - (string) 'cddlib', '4ti2' or 'topcom'

        - ``triangulation_max_height`` - (integer) use a uniform distribution of
          height from 1 to this number

        .. NOTE::

            Any additional argument is forwarded to LattE's executable
            ``count``. All occurrences of '_' will be replaced with a '-'.

        ALGORITHM:

        This method calls the program ``count`` from LattE integrale, a program
        for lattice point enumeration (see
        https://www.math.ucdavis.edu/~latte/).

        EXAMPLES::

            sage: P = Polyhedron(vertices=[(0,0,0),(3,3,3),(-3,2,1),(1,-1,-2)])
            sage: p = P.ehrhart_polynomial()    # optional - latte_int
            sage: p                             # optional - latte_int
            7/2*t^3 + 2*t^2 - 1/2*t + 1
            sage: p(1)                          # optional - latte_int
            6
            sage: len(P.integral_points())
            6
            sage: p(2)                          # optional - latte_int
            36
            sage: len((2*P).integral_points())
            36

        The unit hypercubes::

            sage: from itertools import product
            sage: def hypercube(d):
            ....:     return Polyhedron(vertices=list(product([0,1],repeat=d)))
            sage: hypercube(3).ehrhart_polynomial()   # optional - latte_int
            t^3 + 3*t^2 + 3*t + 1
            sage: hypercube(4).ehrhart_polynomial()   # optional - latte_int
            t^4 + 4*t^3 + 6*t^2 + 4*t + 1
            sage: hypercube(5).ehrhart_polynomial()   # optional - latte_int
            t^5 + 5*t^4 + 10*t^3 + 10*t^2 + 5*t + 1
            sage: hypercube(6).ehrhart_polynomial()   # optional - latte_int
            t^6 + 6*t^5 + 15*t^4 + 20*t^3 + 15*t^2 + 6*t + 1

        An empty polyhedron::

            sage: P = Polyhedron(ambient_dim=3, vertices=[])
            sage: P.ehrhart_polynomial()    # optional - latte_int
            0
            sage: parent(_)                 # optional - latte_int
            Univariate Polynomial Ring in t over Rational Field

        TESTS:

        Test options::

            sage: P = Polyhedron(ieqs=[[1,-1,1,0], [-1,2,-1,0], [1,1,-2,0]], eqns=[[-1,2,-1,-3]], base_ring=ZZ)

            sage: p = P.ehrhart_polynomial(maxdet=5, verbose=True)  # optional - latte_int
            This is LattE integrale ...
            ...
            Invocation: count --ehrhart-polynomial '--redundancy-check=none' '--maxdet=5' --cdd ...
            ...
            sage: p    # optional - latte_int
            1/2*t^2 + 3/2*t + 1

            sage: p = P.ehrhart_polynomial(dual=True, verbose=True)  # optional - latte_int
            This is LattE integrale ...
            ...
            Invocation: count --ehrhart-polynomial '--redundancy-check=none' --dual --cdd ...
            ...
            sage: p   # optional - latte_int
            1/2*t^2 + 3/2*t + 1

            sage: p = P.ehrhart_polynomial(irrational_primal=True, verbose=True)   # optional - latte_int
            This is LattE integrale ...
            ...
            Invocation: count --ehrhart-polynomial '--redundancy-check=none' --irrational-primal --cdd ...
            ...
            sage: p   # optional - latte_int
            1/2*t^2 + 3/2*t + 1

            sage: p = P.ehrhart_polynomial(irrational_all_primal=True, verbose=True)  # optional - latte_int
            This is LattE integrale ...
            ...
            Invocation: count --ehrhart-polynomial '--redundancy-check=none' --irrational-all-primal --cdd ...
            sage: p   # optional - latte_int
            1/2*t^2 + 3/2*t + 1

        Test bad options::

            sage: P.ehrhart_polynomial(bim_bam_boum=19)   # optional - latte_int
            Traceback (most recent call last):
            ...
            RuntimeError: LattE integrale failed with exit code 1 to execute...
        """
        from sage.rings.polynomial.polynomial_ring_constructor import PolynomialRing
        R = PolynomialRing(QQ, 't')
        if self.is_empty():
            return R.zero()

        from sage.misc.misc import SAGE_TMP
        from subprocess import Popen, PIPE

        ine = self.cdd_Hrepresentation()

        args = ['count', '--ehrhart-polynomial']
        if 'redundancy_check' not in kwds:
            args.append('--redundancy-check=none')

        # note: the options below are explicitely written in the function
        # declaration in order to keep tab completion (see #18211).
        kwds.update({
            'dual': dual,
            'irrational_primal': irrational_primal,
            'irrational_all_primal': irrational_all_primal,
            'maxdet': maxdet,
            'no_decomposition': no_decomposition,
            'compute_vertex_cones': compute_vertex_cones,
            'smith_form': smith_form,
            'dualization': dualization,
            'triangulation': triangulation,
            'triangulation_max_height': triangulation_max_height
        })

        for key, value in kwds.items():
            if value is None or value is False:
                continue

            key = key.replace('_', '-')
            if value is True:
                args.append('--{}'.format(key))
            else:
                args.append('--{}={}'.format(key, value))
        args += ['--cdd', '/dev/stdin']

        try:
            # The cwd argument is needed because latte
            # always produces diagnostic output files.
            latte_proc = Popen(args,
                               stdin=PIPE,
                               stdout=PIPE,
                               stderr=(None if verbose else PIPE),
                               cwd=str(SAGE_TMP))
        except OSError:
            from sage.misc.package import PackageNotFoundError
            raise PackageNotFoundError('latte_int')

        ans, err = latte_proc.communicate(ine)
        ret_code = latte_proc.poll()
        if ret_code:
            if err is None:
                err = ", see error message above"
            else:
                err = ":\n" + err
            raise RuntimeError(
                "LattE integrale failed with exit code {} to execute {}".
                format(ret_code, ' '.join(args)) + err.strip())

        p = ans.splitlines()[-2]

        return R(p)
Beispiel #12
0
def integrate(arg, polynomial=None, algorithm='triangulate', raw_output=False, verbose=False, **kwds):
    r"""
    Call to the function integrate from LattE integrale.

    INPUT:

    - ``arg`` -- a cdd or LattE description string.

    - ``polynomial`` -- multivariate polynomial or valid LattE polynomial description string.
      If given, the valuation parameter of LattE is set to integrate, and is set to volume otherwise.

    - ``algorithm`` -- (default: 'triangulate') the integration method. Use 'triangulate' for
      polytope triangulation or 'cone-decompose' for tangent cone decomposition method.

    - ``raw_output`` -- if ``True`` then return directly the output string from LattE.

    - ``verbose`` -- if ``True`` then return directly verbose output from LattE.

    - For all other options of the integrate program, consult the LattE manual.

    OUTPUT:

    Either a string (if ``raw_output`` if set to ``True``) or a rational.

    EXAMPLES::

        sage: from sage.interfaces.latte import integrate
        sage: P = 2 * polytopes.cube()
        sage: x, y, z = polygen(QQ, 'x, y, z')

    Integrating over a polynomial over a polytope in either the H or V representation::

        sage: integrate(P.cdd_Hrepresentation(), x^2*y^2*z^2, cdd=True)   # optional - latte_int
        4096/27
        sage: integrate(P.cdd_Vrepresentation(), x^2*y^2*z^2, cdd=True)   # optional - latte_int
        4096/27

    Computing the volume of a polytope in either the H or V representation::

        sage: integrate(P.cdd_Hrepresentation(), cdd=True)   # optional - latte_int
        64
        sage: integrate(P.cdd_Vrepresentation(), cdd=True)   # optional - latte_int
        64

    Polynomials given as a string in LattE description are also accepted::

        sage: integrate(P.cdd_Hrepresentation(), '[[1,[2,2,2]]]', cdd=True)   # optional - latte_int
        4096/27

    TESTS::

    Testing raw output::

        sage: from sage.interfaces.latte import integrate
        sage: P = polytopes.cuboctahedron()
        sage: cddin = P.cdd_Vrepresentation()
        sage: x, y, z = polygen(QQ, 'x, y, z')
        sage: f = 3*x^2*y^4*z^6 + 7*y^3*z^5
        sage: integrate(cddin, f, cdd=True, raw_output=True)  # optional - latte_int
        '629/47775'

    Testing the ``verbose`` option to integrate over a polytope::

        sage: ans = integrate(cddin, f, cdd=True, verbose=True, raw_output=True)  # optional - latte_int
        This is LattE integrale ...
        ...
        Invocation: integrate --valuation=integrate --triangulate --redundancy-check=none --cdd --monomials=... /dev/stdin
        ...

    Testing triangulate algorithm::

        sage: from sage.interfaces.latte import integrate
        sage: P = polytopes.cuboctahedron()
        sage: cddin = P.cdd_Vrepresentation()
        sage: integrate(cddin, algorithm='triangulate', cdd=True)  # optional - latte_int
        20/3

    Testing convex decomposition algorithm::

        sage: from sage.interfaces.latte import integrate
        sage: P = polytopes.cuboctahedron()
        sage: cddin = P.cdd_Vrepresentation()
        sage: integrate(cddin, algorithm='cone-decompose', cdd=True)  # optional - latte_int
        20/3

    Testing raw output::

        sage: from sage.interfaces.latte import integrate
        sage: P = polytopes.cuboctahedron()
        sage: cddin = P.cdd_Vrepresentation()
        sage: integrate(cddin, cdd=True, raw_output=True)  # optional - latte_int
        '20/3'

    Testing polynomial given as a string in LattE description::

        sage: from sage.interfaces.latte import integrate
        sage: P = polytopes.cuboctahedron()
        sage: integrate(P.cdd_Hrepresentation(), '[[3,[2,4,6]],[7,[0, 3, 5]]]', cdd=True)   # optional - latte_int
        629/47775

    Testing the ``verbose`` option to compute the volume of a polytope::

        sage: from sage.interfaces.latte import integrate
        sage: P = polytopes.cuboctahedron()
        sage: cddin = P.cdd_Vrepresentation()
        sage: ans = integrate(cddin, cdd=True, raw_output=True, verbose=True)  # optional - latte_int
        This is LattE integrale ...
        ...
        Invocation: integrate --valuation=volume --triangulate --redundancy-check=none --cdd /dev/stdin
        ...
    """
    from subprocess import Popen, PIPE
    from sage.misc.misc import SAGE_TMP
    from sage.rings.integer import Integer

    args = ['integrate']

    got_polynomial = True if polynomial is not None else False

    if got_polynomial:
        args.append('--valuation=integrate')
    else:
        args.append('--valuation=volume')

    if algorithm=='triangulate':
        args.append('--triangulate')
    elif algorithm=='cone-decompose':
        args.append('--cone-decompose')

    if 'redundancy_check' not in kwds:
        args.append('--redundancy-check=none')

    for key,value in kwds.items():
        if value is None or value is False:
            continue

        key = key.replace('_','-')
        if value is True:
            args.append('--{}'.format(key))
        else:
            args.append('--{}={}'.format(key, value))

    if got_polynomial:
        if not isinstance(polynomial, six.string_types):
            # transform polynomial to LattE description
            monomials_list = to_latte_polynomial(polynomial)
        else:
            monomials_list = str(polynomial)

        from sage.misc.temporary_file import tmp_filename
        filename_polynomial = tmp_filename()

        with open(filename_polynomial, 'w') as f:
            f.write(monomials_list)
            args += ['--monomials=' + filename_polynomial]

    args += ['/dev/stdin']

    try:
        # The cwd argument is needed because latte
        # always produces diagnostic output files.
        latte_proc = Popen(args,
                           stdin=PIPE, stdout=PIPE,
                           stderr=(None if verbose else PIPE),
                           cwd=str(SAGE_TMP))
    except OSError:
        from sage.misc.package import PackageNotFoundError
        raise PackageNotFoundError('latte_int')

    ans, err = latte_proc.communicate(arg)
    ret_code = latte_proc.poll()
    if ret_code:
        if err is None:
            err = ", see error message above"
        else:
            err = ":\n" + err
        raise RuntimeError("LattE integrale program failed (exit code {})".format(ret_code) + err.strip())

    ans = ans.splitlines()
    ans = ans[-5].split()
    assert(ans[0]=='Answer:')
    ans = ans[1]

    if raw_output:
        return ans
    else:
        from sage.rings.rational import Rational
        return Rational(ans)
Beispiel #13
0
def count(arg, ehrhart_polynomial=False, multivariate_generating_function=False, raw_output=False, verbose=False, **kwds):
    r"""
    Call to the program count from LattE integrale

    INPUT:

    - ``arg`` -- a cdd or LattE description string

    - ``ehrhart_polynomial``, ``multivariate_generating_function``  -- to
      compute Ehrhart polynomial or multivariate generating function instead of
      just counting points

    - ``raw_output`` -- if ``True`` then return directly the output string from LattE

    - For all other options of the count program, consult the LattE manual

    OUTPUT:

    Either a string (if ``raw_output`` if set to ``True``) or an integer (when
    counting points), or a polynomial (if ``ehrhart_polynomial`` is set to
    ``True``) or a multivariate THING (if ``multivariate_generating_function``
    is set to ``True``)

    EXAMPLES::

        sage: from sage.interfaces.latte import count
        sage: P = 2 * polytopes.cube()

    Counting integer points from either the H or V representation::

        sage: count(P.cdd_Hrepresentation(), cdd=True)   # optional - latte_int
        125
        sage: count(P.cdd_Vrepresentation(), cdd=True)   # optional - latte_int
        125

    Ehrhart polynomial::

        sage: count(P.cdd_Hrepresentation(), cdd=True, ehrhart_polynomial=True)  # optional - latte_int
        64*t^3 + 48*t^2 + 12*t + 1

    Multivariate generating function currently only work with ``raw_output=True``::

        sage: opts = {'cdd': True,
        ....:         'multivariate_generating_function': True,
        ....:         'raw_output': True}
        sage: cddin = P.cdd_Hrepresentation()
        sage: print(count(cddin, **opts))  # optional - latte_int
        x[0]^2*x[1]^(-2)*x[2]^(-2)/((1-x[1])*(1-x[2])*(1-x[0]^(-1)))
         + x[0]^(-2)*x[1]^(-2)*x[2]^(-2)/((1-x[1])*(1-x[2])*(1-x[0]))
         + x[0]^2*x[1]^(-2)*x[2]^2/((1-x[1])*(1-x[0]^(-1))*(1-x[2]^(-1)))
         + x[0]^(-2)*x[1]^(-2)*x[2]^2/((1-x[1])*(1-x[0])*(1-x[2]^(-1)))
         + x[0]^2*x[1]^2*x[2]^(-2)/((1-x[2])*(1-x[0]^(-1))*(1-x[1]^(-1)))
         + x[0]^(-2)*x[1]^2*x[2]^(-2)/((1-x[2])*(1-x[0])*(1-x[1]^(-1)))
         + x[0]^2*x[1]^2*x[2]^2/((1-x[0]^(-1))*(1-x[1]^(-1))*(1-x[2]^(-1)))
         + x[0]^(-2)*x[1]^2*x[2]^2/((1-x[0])*(1-x[1]^(-1))*(1-x[2]^(-1)))

    TESTS:

    Testing raw output::

        sage: from sage.interfaces.latte import count
        sage: P = polytopes.cuboctahedron()
        sage: cddin = P.cdd_Vrepresentation()
        sage: count(cddin, cdd=True, raw_output=True)  # optional - latte_int
        '19'
        sage: count(cddin, cdd=True, raw_output=True, ehrhart_polynomial=True) # optional - latte_int
        ' + 1 * t^0 + 10/3 * t^1 + 8 * t^2 + 20/3 * t^3'
        sage: count(cddin, cdd=True, raw_output=True, multivariate_generating_function=True) # optional - latte_int
        'x[0]^(-1)*x[1]^(-1)/((1-x[0]*x[2])*(1-x[0]^(-1)*x[1])*...x[0]^(-1)*x[2]^(-1)))\n'

    Testing the ``verbose`` option::

        sage: n = count(cddin, cdd=True, verbose=True, raw_output=True)  # optional - latte_int
        This is LattE integrale ...
        ...
        Invocation: count '--redundancy-check=none' --cdd /dev/stdin
        ...
        Total Unimodular Cones: ...
        Maximum number of simplicial cones in memory at once: ...
        <BLANKLINE>
        ****  The number of lattice points is:   ****
        Total time: ... sec

    Trivial input for which LattE's preprocessor does all the work::

        sage: P = Polyhedron(vertices=[[0,0,0]])
        sage: cddin = P.cdd_Hrepresentation()
        sage: count(cddin, cdd=True, raw_output=False)  # optional - latte_int
        1

    """
    from subprocess import Popen, PIPE
    from sage.misc.misc import SAGE_TMP
    from sage.rings.integer import Integer

    args = ['count']
    if ehrhart_polynomial and multivariate_generating_function:
        raise ValueError
    if ehrhart_polynomial:
        args.append('--ehrhart-polynomial')
    elif multivariate_generating_function:
        args.append('--multivariate-generating-function')

    if 'redundancy_check' not in kwds:
        args.append('--redundancy-check=none')

    for key,value in kwds.items():
        if value is None or value is False:
            continue

        key = key.replace('_','-')
        if value is True:
            args.append('--{}'.format(key))
        else:
            args.append('--{}={}'.format(key, value))

    if multivariate_generating_function:
        from sage.misc.temporary_file import tmp_filename
        filename = tmp_filename()
        with open(filename, 'w') as f:
            f.write(arg)
        args += [filename]
    else:
        args += ['/dev/stdin']

    try:
        # The cwd argument is needed because latte
        # always produces diagnostic output files.
        latte_proc = Popen(args,
                           stdin=PIPE, stdout=PIPE,
                           stderr=(None if verbose else PIPE),
                           cwd=str(SAGE_TMP))
    except OSError:
        from sage.misc.package import PackageNotFoundError
        raise PackageNotFoundError('latte_int')

    ans, err = latte_proc.communicate(arg)
    ret_code = latte_proc.poll()
    if ret_code:
        if err is None:
            err = ", see error message above"
        else:
            err = ":\n" + err
        raise RuntimeError("LattE integrale program failed (exit code {})".format(ret_code) + err.strip())


    if ehrhart_polynomial:
        ans = ans.splitlines()[-2]
        if raw_output:
            return ans
        else:
            from sage.rings.polynomial.polynomial_ring_constructor import PolynomialRing
            from sage.rings.rational_field import QQ
            R = PolynomialRing(QQ, 't')
            return R(ans)
    elif multivariate_generating_function:
        with open(filename + '.rat') as f:
            ans = f.read()
        if raw_output:
            return ans
        else:
            raise NotImplementedError("there is no Sage object to handle multivariate series from LattE, use raw_output=True")
    else:
        if ans: # Sometimes (when LattE's preproc does the work), no output appears on stdout.
            ans = ans.splitlines()[-1]
        if not ans:
            # opening a file is slow (30e-6s), so we read the file
            # numOfLatticePoints only in case of a IndexError above
            with open(SAGE_TMP+'/numOfLatticePoints', 'r') as f:
                ans = f.read()

        if raw_output:
            return ans
        else:
            from sage.rings.integer import Integer
            return Integer(ans)
Beispiel #14
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, PackageNotFoundError

    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 PackageNotFoundError("database_gap")
        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
Beispiel #15
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