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 = []
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);')
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);')
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))
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))
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))
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]]
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 = []
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])
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
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)
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)
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)
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
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