def solve(self, facets): """ EXAMPLES:: sage: from sage.interfaces.rubik import * sage: C = RubiksCube("R U") sage: CubexSolver().solve(C.facets()) 'R U' sage: C = RubiksCube("R U F L B D") sage: sol = CubexSolver().solve(C.facets()); sol "U' L' L' U L U' L U D L L D' L' D L' D' L D L' U' L D' L' U L' B' U' L' U B L D L D' U' L' U L B L B' L' U L U' L' F' L' F L' F L F' L' D' L' D D L D' B L B' L B' L B F' L F F B' L F' B D' D' L D B' B' L' D' B U' U' L' B' D' F' F' L D F'" sage: RubiksCube(sol) == C True sage: C = RubiksCube("R2 F'") sage: CubexSolver().solve(C.facets()) "R' R' F'" sage: C = RubiksCube().scramble() sage: sol = CubexSolver().solve(C.facets()) sage: C == RubiksCube(sol) True """ s = self.format_cube(facets) child = pexpect.spawn(self.__cmd+" "+s) ix = child.expect(['210.*?:', '^5\d+(.*)']) if ix == 0: child.expect(['211', pexpect.EOF]) moves = bytes_to_str(child.before).strip().replace(',', '').split(' ') return " ".join([move_map[m] for m in reversed(moves)]) else: s = child.after while child.expect(['^5\d+', pexpect.EOF]) == 0: s += child.after raise ValueError(bytes_to_str(s))
def solve(self, facets): """ EXAMPLES:: sage: from sage.interfaces.rubik import * sage: C = RubiksCube("R U") sage: CubexSolver().solve(C.facets()) 'R U' sage: C = RubiksCube("R U F L B D") sage: sol = CubexSolver().solve(C.facets()); sol "U' L' L' U L U' L U D L L D' L' D L' D' L D L' U' L D' L' U L' B' U' L' U B L D L D' U' L' U L B L B' L' U L U' L' F' L' F L' F L F' L' D' L' D D L D' B L B' L B' L B F' L F F B' L F' B D' D' L D B' B' L' D' B U' U' L' B' D' F' F' L D F'" sage: RubiksCube(sol) == C True sage: C = RubiksCube("R2 F'") sage: CubexSolver().solve(C.facets()) "R' R' F'" sage: C = RubiksCube().scramble() sage: sol = CubexSolver().solve(C.facets()) sage: C == RubiksCube(sol) True """ s = self.format_cube(facets) child = pexpect.spawn(self.__cmd + " " + s) ix = child.expect(['210.*?:', '^5\d+(.*)']) if ix == 0: child.expect(['211', pexpect.EOF]) moves = bytes_to_str(child.before).strip().replace(',', '').split(' ') return " ".join([move_map[m] for m in reversed(moves)]) else: s = child.after while child.expect(['^5\d+', pexpect.EOF]) == 0: s += child.after raise ValueError(bytes_to_str(s))
def test(self, *filenames): r""" Print an error message if the given files are not using valid Python 3 syntax. INPUT: - ``*filenames`` -- the fully qualified filenames to check EXAMPLES:: sage: import os, tempfile sage: src = tempfile.NamedTemporaryFile(suffix='.py', mode='w+', delete=False) sage: _ = src.write('print "invalid print statement"') sage: src.close() sage: from sage.tests.py3_syntax import Python3SyntaxTest sage: py3_syntax = Python3SyntaxTest() sage: py3_syntax.test(src.name) Invalid Python 3 syntax found: Missing parentheses in call to 'print'. Did you mean print("invalid print statement")? (...py, line 1) sage: os.unlink(src.name) """ # compile all given files in memory, printing all errors # inspired by the py_compile module (but without writing to file) script = """ import sys import importlib.machinery rv = 0 for file in sys.argv[1:]: loader = importlib.machinery.SourceFileLoader('<sage_test>', file) source_bytes = loader.get_data(file) try: code = loader.source_to_code(source_bytes, file) except Exception as err: print(err) rv = 1 sys.exit(rv) """ cmd = [ 'python3', '-c', script, ] + list(filenames) process = subprocess.Popen( cmd, env=PYTHON3_ENV, stdout=subprocess.PIPE, stderr=subprocess.PIPE ) stdout, stderr = process.communicate() if process.returncode == 0: return print('Invalid Python 3 syntax found:') if stdout: print(bytes_to_str(stdout)) if stderr: print(bytes_to_str(stderr))
def solve(self, facets, timeout=10, extra_time=2): """ EXAMPLES:: sage: from sage.interfaces.rubik import * sage: C = RubiksCube().move("R U") sage: DikSolver().solve(C.facets()) 'R U' sage: C = RubiksCube().move("R U F L B D") sage: DikSolver().solve(C.facets()) 'R U F L B D' sage: C = RubiksCube().move("R2 F'") sage: DikSolver().solve(C.facets()) "R2 F'" """ cube_str = self.format_cube(facets) child = pexpect.spawn(self.__cmd + " -p") child.expect('Initialization done!') child.sendline(cube_str) # We use send(chr(4)) instead of sendeof in this case, since # child.sendoef() when run in the background with the Dik solver # sends a SIGTTOU which suspends the process -- this is very bad. # This is only a temporary workaround, and does not fix the problem # on OS X. The Dik C program itself will need to be fixed. # See trac #1683. (TODO) -- willem jp, wstein, mabshoff child.send(chr(4)) #child.sendeof() ix = child.expect(['Solution[^\n]*:', pexpect.EOF, pexpect.TIMEOUT], timeout=timeout) if ix == 0: child.expect(['[^\n]+']) sol = child.after.strip() start_time = time.time() while extra_time > time.time() - start_time: ix = child.expect( ['Solution[^\n]*:', pexpect.EOF, pexpect.TIMEOUT], timeout=extra_time - int(time.time() - start_time)) if ix == 0: child.expect(['[^\n]+']) sol = child.after.strip() else: extra_time = 0 # format the string into our notation child.close(True) sol = bytes_to_str(sol) return ' '.join([ self.rot_map[m[0]] + str(4 - int(m[1])) for m in reversed(sol.split(' ')) ]).replace('1', '').replace('3', "'") elif ix == 1: # invalid format child.close(True) raise ValueError(bytes_to_str(child.before)) else: child.close(True) raise RuntimeError("timeout")
def solve(self, facets, timeout=10, extra_time=2): """ EXAMPLES:: sage: from sage.interfaces.rubik import * sage: C = RubiksCube().move("R U") sage: DikSolver().solve(C.facets()) 'R U' sage: C = RubiksCube().move("R U F L B D") sage: DikSolver().solve(C.facets()) 'R U F L B D' sage: C = RubiksCube().move("R2 F'") sage: DikSolver().solve(C.facets()) "R2 F'" """ cube_str = self.format_cube(facets) child = pexpect.spawn(self.__cmd+" -p") child.expect('Initialization done!') child.sendline(cube_str) # We use send(chr(4)) instead of sendeof in this case, since # child.sendoef() when run in the background with the Dik solver # sends a SIGTTOU which suspends the process -- this is very bad. # This is only a temporary workaround, and does not fix the problem # on OS X. The Dik C program itself will need to be fixed. # See trac #1683. (TODO) -- willem jp, wstein, mabshoff child.send(chr(4)) #child.sendeof() ix = child.expect(['Solution[^\n]*:', pexpect.EOF, pexpect.TIMEOUT], timeout=timeout) if ix == 0: child.expect(['[^\n]+']) sol = child.after.strip() start_time = time.time() while extra_time > time.time() - start_time: ix = child.expect(['Solution[^\n]*:', pexpect.EOF, pexpect.TIMEOUT], timeout=extra_time - int(time.time() - start_time)) if ix == 0: child.expect(['[^\n]+']) sol = child.after.strip() else: extra_time = 0 # format the string into our notation child.close(True) sol = bytes_to_str(sol) return ' '.join([self.rot_map[m[0]]+str(4-int(m[1])) for m in reversed(sol.split(' '))]).replace('1', '').replace('3',"'") elif ix == 1: # invalid format child.close(True) raise ValueError(bytes_to_str(child.before)) else: child.close(True) raise RuntimeError("timeout")
def is_functional(self): r""" Test whether ``lrs`` works on a trivial input. EXAMPLES:: sage: from sage.features.lrs import Lrs sage: Lrs().is_functional() # optional: lrslib FeatureTestResult('lrslib', True) """ from sage.misc.temporary_file import tmp_filename tf_name = tmp_filename() with open(tf_name, 'wb') as tf: tf.write(str_to_bytes("V-representation\nbegin\n 1 1 rational\n 1 \nend\nvolume")) devnull = open(os.devnull, 'wb') command = ['lrs', tf_name] try: lines = bytes_to_str(subprocess.check_output(command, stderr=devnull)) except subprocess.CalledProcessError as e: return FeatureTestResult(self, False, reason="Call to `{command}` failed with exit code {e.returncode}.".format(command=" ".join(command), e=e)) expected_list = ["Volume= 1", "Volume=1"] if all(lines.find(expected) == -1 for expected in expected_list): print(lines) return FeatureTestResult(self, False, reason="Output of `{command}` did not contain the expected result {expected}.".format( command=" ".join(command), expected=" or ".join(expected_list))) return FeatureTestResult(self, True)
def mtllib(self): """ Return the ``mtllib`` filename The ``mtllib`` line in the Wavefront file format (``*.obj``) is the name of the separate texture file. OUTPUT: String. The filename under which ``mtl`` is supposed to be saved. EXAMPLES:: sage: from sage.repl.rich_output.output_catalog import OutputSceneWavefront sage: rich_output = OutputSceneWavefront.example() sage: rich_output.mtllib() 'scene.mtl' """ marker = b'mtllib ' for line in self.obj.get().splitlines(): if line.startswith(marker): return bytes_to_str(line[len(marker):], FS_ENCODING, 'surrogateescape') return 'scene.mtl'
def completions(self, s): """ Return all commands that complete the command starting with the string s. EXAMPLES:: sage: c = giac.completions('cas') sage: 'cas_setup' in c True """ if self._expect is None: self._start() E = self._expect E.sendline('%s%s%s'%(s,chr(63),chr(13))) t = E.timeout E.timeout=0.3 # since some things have no completion try: E.expect('----') except pexpect.TIMEOUT: E.timeout = t return [] E.timeout = t v = bytes_to_str(E.before) E.expect(self._prompt) E.expect(self._prompt) return v.split()[1:]
def _dbz_to_string(name): r""" TESTS:: sage: from sage.databases.db_modular_polynomials import _dbz_to_string sage: _dbz_to_string('PolMod/Atk/pol.002.dbz') # optional - database_kohel '3 0 1 \n2 1 -1 \n2 0 744 \n1 1 -1 \n1 0 184512 \n0 2 1 \n0 1 7256 \n0 0 15252992 \n' sage: _dbz_to_string('PolMod/Cls/pol.001.dbz') # optional - database_kohel '1 0 1 \n' sage: _dbz_to_string('PolMod/Eta/pol.002.dbz') # optional - database_kohel '3 0 1 \n2 0 48 \n1 1 -1 \n1 0 768 \n0 0 4096 \n' sage: _dbz_to_string('PolMod/EtaCrr/crr.02.002.dbz') # optional - database_kohel '2 1 1 \n2 0 -48 \n1 1 2304 \n0 2 -4096 \n0 1 196608 \n' sage: _dbz_to_string('PolHeeg/Cls/0000001-0005000/pol.0000003.dbz') # optional - database_kohel '0\n1\n' """ from sage.env import SAGE_SHARE dblocation = os.path.join(SAGE_SHARE, 'kohel') filename = os.path.join(dblocation, name) try: with open(filename, 'rb') as f: data = bz2.decompress(f.read()) except IOError: raise ValueError('file not found in the Kohel database') return bytes_to_str(data)
def completions(self, s): """ Return all commands that complete the command starting with the string s. EXAMPLES:: sage: c = giac.completions('cas') sage: 'cas_setup' in c True """ if self._expect is None: self._start() E = self._expect E.sendline('%s%s%s' % (s, chr(63), chr(13))) t = E.timeout E.timeout = 0.3 # since some things have no completion try: E.expect('----') except pexpect.TIMEOUT: E.timeout = t return [] E.timeout = t v = bytes_to_str(E.before) E.expect(self._prompt) E.expect(self._prompt) return v.split()[1:]
def iscc_card(arg): r""" EXAMPLES:: sage: from surface_dynamics import * sage: from surface_dynamics.misc.iscc import iscc_card sage: cd = CylinderDiagram('(0,1)-(0,2) (2)-(1)') sage: iscc_card(cd) # optional - barvinok '[w0, w1] -> { 1 : 0 <= w1 <= w0 }' sage: r = RibbonGraph(faces='(0,2,4,6,7)(8,9,5,3,1)', edges='(0,1)(2,3)(4,5)(6,7)(8,9)') sage: iscc_card(r) # optional - barvinok '[b0, b1] -> { (((1 - 1/8 * b0) + 17/12 * b1 + 5/8 * b1^2 + 1/12 * b1^3) + 1/4 * floor((2b0)/4)) : (b0 + b1) mod 2 = 0 and 0 <= b1 <= -2 + b0; ((1 + 31/24 * b0 + 5/8 * b0^2 + 1/12 * b0^3) + 1/4 * floor((2b0)/4)) : (b0 + b1) mod 2 = 0 and b0 >= 0 and b1 >= b0 }' """ from surface_dynamics.flat_surfaces.separatrix_diagram import CylinderDiagram from surface_dynamics.flat_surfaces.homology import RibbonGraph if isinstance(arg, CylinderDiagram): poly = iscc_cd_string(arg) elif isinstance(arg, RibbonGraph): poly = iscc_rg_string(arg) from subprocess import Popen, PIPE cmd = 'P := {};\n'.format(poly) cmd += 'q := card P;\n' cmd += 'q;' proc = Popen(['iscc'], stdin=PIPE, stdout=PIPE, stderr=PIPE) ans, err = proc.communicate(str_to_bytes(cmd)) return bytes_to_str(ans).strip()
def is_functional(self): r""" Check whether ``theta`` works on a trivial example. EXAMPLES:: sage: from sage.features.csdp import CSDP sage: CSDP().is_functional() # optional: csdp FeatureTestResult('CSDP', True) """ from sage.misc.temporary_file import tmp_filename tf_name = tmp_filename() with open(tf_name, 'wb') as tf: tf.write("2\n1\n1 1".encode()) with open(os.devnull, 'wb') as devnull: command = ['theta', tf_name] try: lines = subprocess.check_output(command, stderr=devnull) except subprocess.CalledProcessError as e: return FeatureTestResult(self, False, reason="Call to `{command}` failed with exit code {e.returncode}." .format(command=" ".join(command), e=e)) result = bytes_to_str(lines).strip().split('\n')[-1] match = re.match("^The Lovasz Theta Number is (.*)$", result) if match is None: return FeatureTestResult(self, False, reason="Last line of the output of `{command}` did not have the expected format." .format(command=" ".join(command))) return FeatureTestResult(self, True)
def _pprof(self): """ Return the name of the ``pprof`` binary. OUTPUT: String. The name of the gperftools ``pprof`` utility. A ``OSError`` is raised if it cannot be found. EXAMPLES:: sage: from sage.misc.gperftools import Profiler sage: prof = Profiler() sage: try: ....: pp = prof._pprof() ....: assert isinstance(pp, str) ....: except OSError: ....: pass # not installed """ potential_names = ['google-pprof', 'pprof'] from subprocess import check_output, CalledProcessError, STDOUT for name in potential_names: try: version = check_output([name, '--version'], stderr=STDOUT) except (CalledProcessError, OSError): continue version = bytes_to_str(version) if 'gperftools' not in version: from warnings import warn warn( 'the "{0}" utility does not appear to be the gperftools profiler' .format(name), RuntimeWarning) continue return name raise OSError('unable to run pprof, please install gperftools')
def load_wrap(filename, attach=False): """ Encodes a load or attach command as valid Python code. INPUT: - ``filename`` - a string; the argument to the load or attach command - ``attach`` - a boolean (default: False); whether to attach ``filename``, instead of loading it OUTPUT: - a string EXAMPLES:: sage: sage.repl.load.load_wrap('foo.py', True) 'sage.repl.load.load(sage.repl.load.base64.b64decode("Zm9vLnB5"),globals(),True)' sage: sage.repl.load.load_wrap('foo.sage') 'sage.repl.load.load(sage.repl.load.base64.b64decode("Zm9vLnNhZ2U="),globals(),False)' sage: m = sage.repl.load.base64.b64decode("Zm9vLnNhZ2U=") sage: m == b'foo.sage' True """ # Note: On Python 3 b64encode only accepts bytes, and returns bytes (yet # b64decode does accept str, but always returns bytes) b64 = base64.b64encode(str_to_bytes(filename, FS_ENCODING, "surrogateescape")) return 'sage.repl.load.load(sage.repl.load.base64.b64decode("{}"),globals(),{})'.format( bytes_to_str(b64, 'ascii'), attach)
def load_wrap(filename, attach=False): """ Encode a load or attach command as valid Python code. INPUT: - ``filename`` - a string; the argument to the load or attach command - ``attach`` - a boolean (default: False); whether to attach ``filename``, instead of loading it OUTPUT: - a string EXAMPLES:: sage: sage.repl.load.load_wrap('foo.py', True) 'sage.repl.load.load(sage.repl.load.base64.b64decode("Zm9vLnB5"),globals(),True)' sage: sage.repl.load.load_wrap('foo.sage') 'sage.repl.load.load(sage.repl.load.base64.b64decode("Zm9vLnNhZ2U="),globals(),False)' sage: m = sage.repl.load.base64.b64decode("Zm9vLnNhZ2U=") sage: m == b'foo.sage' True """ # Note: In Python 3, b64encode only accepts bytes, and returns bytes. b64 = base64.b64encode(str_to_bytes(filename, FS_ENCODING, "surrogateescape")) txt = 'sage.repl.load.load(sage.repl.load.base64.b64decode("{}"),globals(),{})' return txt.format(bytes_to_str(b64, 'ascii'), attach)
def is_jvm_available(self): """ Returns True if the Java Virtual Machine is available and False if not. EXAMPLES: Check that it returns a boolean:: sage: from sage.interfaces.jmoldata import JmolData sage: JData = JmolData() sage: type(JData.is_jvm_available()) <... 'bool'> """ try: version = bytes_to_str( subprocess.check_output(['java', '-version'], stderr=subprocess.STDOUT)) except (subprocess.CalledProcessError, OSError): return False java_version_number = int( re.sub(r'.*version "(0\.|1\.)?(\d*)[\s\S]*', r'\2', version, flags=re.S)) return java_version_number >= 7
def solve(self, facets): """ The initial startup and precomputation are substantial... TODO: Let it keep searching once it found a solution? EXAMPLES:: sage: from sage.interfaces.rubik import * sage: solver = DikSolver() sage: solver = OptimalSolver() # long time (28s on sage.math, 2012) Initializing tables... Done. sage: C = RubiksCube("R U") sage: solver.solve(C.facets()) 'R U' sage: C = RubiksCube("R U F L B D") sage: solver.solve(C.facets()) 'R U F L B D' sage: C = RubiksCube("R2 D2") sage: solver.solve(C.facets()) 'R2 D2' """ self.ready() self.child.sendline(self.format_cube(facets)) self.child.expect(r"([LRUDBF'2 ]+)\s+\((\d+)q\*?, (\d+)f\*?\)") self.child.sendline(chr(3)) # send ctrl-c return bytes_to_str(self.child.match.groups()[0]).strip()
def best_known_covering_design_www(v, k, t, verbose=False): r""" Return the best known `(v, k, t)` covering design from an online database. This uses the La Jolla Covering Repository, a database available at `<https://ljcr.dmgordon.org/cover.html>`_ INPUT: - ``v`` -- integer, the size of the point set for the design - ``k`` -- integer, the number of points per block - ``t`` -- integer, the size of sets covered by the blocks - ``verbose`` -- bool (default: ``False``), print verbose message OUTPUT: A :class:`CoveringDesign` object representing the ``(v, k, t)``-covering design with smallest number of blocks available in the database. EXAMPLES:: sage: from sage.combinat.designs.covering_design import ( # optional - internet ....: best_known_covering_design_www) sage: C = best_known_covering_design_www(7, 3, 2) # optional - internet sage: print(C) # optional - internet C(7, 3, 2) = 7 Method: lex covering Submitted on: 1996-12-01 00:00:00 0 1 2 0 3 4 0 5 6 1 3 5 1 4 6 2 3 6 2 4 5 A ValueError is raised if the ``(v, k, t)`` parameters are not found in the database. """ v = int(v) k = int(k) t = int(t) param = "?v=%s&k=%s&t=%s" % (v, k, t) url = "https://ljcr.dmgordon.org/cover/get_cover.php" + param if verbose: print("Looking up the bounds at %s" % url) f = urlopen(url) try: s = bytes_to_str(f.read()) finally: f.close() if 'covering not in database' in s: # not found str = "no (%d, %d, %d) covering design in database\n" % (v, k, t) raise ValueError(str) return sage_eval(s)
def from_sparse6(G, g6_string): r""" Fill ``G`` with the data of a sparse6 string. INPUT: - ``G`` -- a graph - ``g6_string`` -- a sparse6 string EXAMPLES:: sage: from sage.graphs.graph_input import from_sparse6 sage: g = Graph() sage: from_sparse6(g, ':I`ES@obGkqegW~') sage: g.is_isomorphic(graphs.PetersenGraph()) True """ from .generic_graph_pyx import length_and_string_from_graph6, int_to_binary_string if isinstance(g6_string, bytes): g6_string = bytes_to_str(g6_string) elif not isinstance(g6_string, str): raise ValueError('if input format is graph6, then g6_string must be a string') n = g6_string.find('\n') if n == -1: n = len(g6_string) s = g6_string[:n] n, s = length_and_string_from_graph6(s[1:]) if not n: edges = [] else: from sage.rings.integer_ring import ZZ k = int((ZZ(n) - 1).nbits()) ords = [ord(i) for i in s] if any(o > 126 or o < 63 for o in ords): raise RuntimeError("the string seems corrupt: valid characters are \n" + ''.join([chr(i) for i in range(63,127)])) bits = ''.join([int_to_binary_string(o-63).zfill(6) for o in ords]) if not k: b = [int(x) for x in bits] x = [0] * len(b) else: b = [] x = [] for i in range(0, len(bits)-k, k+1): b.append(int(bits[i:i+1], 2)) x.append(int(bits[i+1:i+k+1], 2)) v = 0 edges = [] for i in range(len(b)): v += b[i] # +1 if b[i] == 1 else 0 if x[i] > v: v = x[i] else: if v < n: edges.append((x[i], v)) G.add_vertices(range(n)) G.add_edges(edges)
def _execute_line(self, line, wait_for_prompt=True, expect_eof=False): r""" Execute a line of code in GAP3 and parse the output. TESTS: Test that syntax errors are handled correctly:: sage: gap3('syntax error', name='x') #optional - gap3 Traceback (most recent call last): ... TypeError: Gap3 produced error output Syntax error: ; expected x:=syntax error; ^ gap> ... Test that error messages are detected and reported correctly:: sage: gap3.SymmetricGroup(5,3) #optional - gap3 Traceback (most recent call last): ... RuntimeError: Gap3 produced error output Error, Record: left operand must be a record at return arg[1].operations.SymmetricGroup( arg[1], arg[2] ) ... in SymmetricGroup( ..., ... ) called from main loop brk> quit; ... Test that break loops are detected and exited properly:: sage: f = gap3('function(L) return L[0]; end;;') #optional - gap3 sage: f([1,2,3]) #optional - gap3 Traceback (most recent call last): ... RuntimeError: Gap3 produced error output Error, List Element: <position> must be a positive integer at return L[0] ... in ... called from main loop brk> quit; ... """ # It seems that GAP3 does not classify syntax errors as regular error # messages, so the generic GAP interface processing code does not # detect it. So we test for a syntax error explicitly. normal_output, error_output = \ super(Gap3, self)._execute_line(line, wait_for_prompt=True, expect_eof=False) normal = bytes_to_str(normal_output) if normal.startswith("Syntax error:"): normal_output, error_output = "", normal_output return (normal_output, error_output)
def hadamard_matrix_www(url_file, comments=False): """ Pull file from Sloane's database and return the corresponding Hadamard matrix as a Sage matrix. You must input a filename of the form "had.n.xxx.txt" as described on the webpage http://neilsloane.com/hadamard/, where "xxx" could be empty or a number of some characters. If ``comments=True`` then the "Automorphism..." line of the had.n.xxx.txt file is printed if it exists. Otherwise nothing is done. EXAMPLES:: sage: hadamard_matrix_www("had.4.txt") # optional - internet [ 1 1 1 1] [ 1 -1 1 -1] [ 1 1 -1 -1] [ 1 -1 -1 1] sage: hadamard_matrix_www("had.16.2.txt",comments=True) # optional - internet Automorphism group has order = 49152 = 2^14 * 3 [ 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1] [ 1 -1 1 -1 1 -1 1 -1 1 -1 1 -1 1 -1 1 -1] [ 1 1 -1 -1 1 1 -1 -1 1 1 -1 -1 1 1 -1 -1] [ 1 -1 -1 1 1 -1 -1 1 1 -1 -1 1 1 -1 -1 1] [ 1 1 1 1 -1 -1 -1 -1 1 1 1 1 -1 -1 -1 -1] [ 1 -1 1 -1 -1 1 -1 1 1 -1 1 -1 -1 1 -1 1] [ 1 1 -1 -1 -1 -1 1 1 1 1 -1 -1 -1 -1 1 1] [ 1 -1 -1 1 -1 1 1 -1 1 -1 -1 1 -1 1 1 -1] [ 1 1 1 1 1 1 1 1 -1 -1 -1 -1 -1 -1 -1 -1] [ 1 1 1 1 -1 -1 -1 -1 -1 -1 -1 -1 1 1 1 1] [ 1 1 -1 -1 1 -1 1 -1 -1 -1 1 1 -1 1 -1 1] [ 1 1 -1 -1 -1 1 -1 1 -1 -1 1 1 1 -1 1 -1] [ 1 -1 1 -1 1 -1 -1 1 -1 1 -1 1 -1 1 1 -1] [ 1 -1 1 -1 -1 1 1 -1 -1 1 -1 1 1 -1 -1 1] [ 1 -1 -1 1 1 1 -1 -1 -1 1 1 -1 -1 -1 1 1] [ 1 -1 -1 1 -1 -1 1 1 -1 1 1 -1 1 1 -1 -1] """ n = eval(url_file.split(".")[1]) rws = [] url = "http://neilsloane.com/hadamard/" + url_file with urlopen(url) as f: s = [bytes_to_str(line) for line in f.readlines()] for i in range(n): line = s[i] rws.append([1 if line[j] == "+" else -1 for j in range(n)]) if comments: lastline = s[-1] if lastline[0] == "A": print(lastline) return matrix(rws)
def script(self): r""" Return the JMol script file. This method extracts the Jmol script from the Jmol spt file (a zip archive) and inlines meshes. OUTPUT: String. EXAMPLES:: sage: from sage.repl.display.jsmol_iframe import JSMolHtml sage: from sage.repl.rich_output.output_graphics3d import OutputSceneJmol sage: jsmol = JSMolHtml(OutputSceneJmol.example(), width=500, height=300) sage: jsmol.script() 'data "model list"\n10\nempt...aliasdisplay on;\n' """ script = [] with self._zip.open('SCRIPT') as SCRIPT: for line in SCRIPT: if line.startswith(b'pmesh'): command, obj, meshfile = line.split(b' ', 3) assert command == b'pmesh' if meshfile not in [b'dots\n', b'mesh\n']: assert (meshfile.startswith(b'"') and meshfile.endswith(b'"\n')) meshfile = meshfile[1:-2] # strip quotes script += [ 'pmesh {0} inline "'.format(bytes_to_str(obj)), bytes_to_str(self._zip.open(meshfile).read()), '"\n' ] continue script += [bytes_to_str(line)] return ''.join(script)
def script(self): r""" Return the JMol script file. This method extracts the Jmol script from the Jmol spt file (a zip archive) and inlines meshes. OUTPUT: String. EXAMPLES:: sage: from sage.repl.display.jsmol_iframe import JSMolHtml sage: from sage.repl.rich_output.output_graphics3d import OutputSceneJmol sage: jsmol = JSMolHtml(OutputSceneJmol.example(), width=500, height=300) sage: jsmol.script() 'data "model list"\n10\nempt...aliasdisplay on;\n' """ script = [] with self._zip.open('SCRIPT') as SCRIPT: for line in SCRIPT: if line.startswith(b'pmesh'): command, obj, meshfile = line.split(b' ', 3) assert command == b'pmesh' if meshfile not in [b'dots\n', b'mesh\n']: assert (meshfile.startswith(b'"') and meshfile.endswith(b'"\n')) meshfile = bytes_to_str(meshfile[1:-2]) # strip quotes script += [ 'pmesh {0} inline "'.format(bytes_to_str(obj)), bytes_to_str(self._zip.open(meshfile).read()), '"\n' ] continue script += [bytes_to_str(line)] return ''.join(script)
def from_graph6(G, g6_string): r""" Fill ``G`` with the data of a graph6 string. INPUT: - ``G`` -- a graph - ``g6_string`` -- a graph6 string EXAMPLES:: sage: from sage.graphs.graph_input import from_graph6 sage: g = Graph() sage: from_graph6(g, 'IheA@GUAo') sage: g.is_isomorphic(graphs.PetersenGraph()) True """ from .generic_graph_pyx import length_and_string_from_graph6, binary_string_from_graph6 if isinstance(g6_string, bytes): g6_string = bytes_to_str(g6_string) elif not isinstance(g6_string, str): raise ValueError( 'if input format is graph6, then g6_string must be a string') n = g6_string.find('\n') if n == -1: n = len(g6_string) ss = g6_string[:n] n, s = length_and_string_from_graph6(ss) m = binary_string_from_graph6(s, n) expected = n * (n - 1) // 2 + (6 - n * (n - 1) // 2) % 6 if len(m) > expected: raise RuntimeError( "the string (%s) seems corrupt: for n = %d, the string is too long" % (ss, n)) elif len(m) < expected: raise RuntimeError( "the string (%s) seems corrupt: for n = %d, the string is too short" % (ss, n)) G.add_vertices(range(n)) k = 0 for i in range(n): for j in range(i): if m[k] == '1': G._backend.add_edge(i, j, None, False) k += 1
def _get(self, timeout=0.1): """ Used internally to get information about what has been computed so far. """ if self._done: return self._out e = self._p try: e.expect('xxx', timeout=timeout) except pexpect.TIMEOUT: pass except pexpect.EOF: self._done = True self._p.close() self._out += bytes_to_str(e.before) return self._out
def from_dig6(G, dig6_string): r""" Fill ``G`` with the data of a dig6 string. INPUT: - ``G`` -- a graph - ``dig6_string`` -- a dig6 string EXAMPLES:: sage: from sage.graphs.graph_input import from_dig6 sage: g = DiGraph() sage: from_dig6(g, digraphs.Circuit(10).dig6_string()) sage: g.is_isomorphic(digraphs.Circuit(10)) True """ from .generic_graph_pyx import length_and_string_from_graph6, binary_string_from_dig6 if isinstance(dig6_string, bytes): dig6_string = bytes_to_str(dig6_string) elif not isinstance(dig6_string, str): raise ValueError( 'if input format is dig6, then dig6_string must be a string') n = dig6_string.find('\n') if n == -1: n = len(dig6_string) ss = dig6_string[:n] n, s = length_and_string_from_graph6(ss) m = binary_string_from_dig6(s, n) expected = n**2 if len(m) > expected: raise RuntimeError( "the string (%s) seems corrupt: for n = %d, the string is too long" % (ss, n)) elif len(m) < expected: raise RuntimeError( "the string (%s) seems corrupt: for n = %d, the string is too short" % (ss, n)) G.add_vertices(range(n)) k = 0 for i in range(n): for j in range(n): if m[k] == '1': G._backend.add_edge(i, j, None, True) k += 1
def _get(self, timeout=0.1): """ Used internally to get information about what has been computed so far. """ if self._done: return self._out e = self._p try: e.expect('xxx', timeout=timeout) except pexpect.TIMEOUT: pass except pexpect.EOF: pass self._done = True self._p.close() self._out += bytes_to_str(e.before) return self._out
def html_fragment(self): """ Return a self-contained HTML fragment displaying the image This is a workaround for the Jupyter notebook which doesn't support GIF directly. OUTPUT: String. HTML fragment for displaying the GIF image. EXAMPLES:: sage: from sage.repl.rich_output.output_catalog import OutputImageGif sage: OutputImageGif.example().html_fragment() '<img src="data:image/gif;base64,R0lGODl...zd3t/g4eLj5OVDQQA7"/>' """ b64 = bytes_to_str(base64.b64encode(self.gif.get()), 'ascii') return '<img src="data:image/gif;base64,{0}"/>'.format(b64)
def _eval_line(self, line, reformat=True, allow_use_file=False, wait_for_prompt=True, restart_if_needed=False): """ EXAMPLES:: sage: print(octave._eval_line('2+2')) #optional - octave ans = 4 """ from pexpect.exceptions import EOF if not wait_for_prompt: return Expect._eval_line(self, line) if line == '': return '' if self._expect is None: self._start() if allow_use_file and len(line) > 3000: return self._eval_line_using_file(line) try: E = self._expect # debug # self._synchronize(cmd='1+%s\n') verbose("in = '%s'" % line, level=3) E.sendline(line) E.expect(self._prompt) out = bytes_to_str(E.before) # debug verbose("out = '%s'" % out, level=3) except EOF: if self._quit_string() in line: return '' except KeyboardInterrupt: self._keyboard_interrupt() try: if reformat: if 'syntax error' in out: raise SyntaxError(out) out = "\n".join(out.splitlines()[1:]) return out except NameError: return ''
def from_graph6(G, g6_string): r""" Fill ``G`` with the data of a graph6 string. INPUT: - ``G`` -- a graph - ``g6_string`` -- a graph6 string EXAMPLES:: sage: from sage.graphs.graph_input import from_graph6 sage: g = Graph() sage: from_graph6(g, 'IheA@GUAo') sage: g.is_isomorphic(graphs.PetersenGraph()) True """ from .generic_graph_pyx import length_and_string_from_graph6, binary_string_from_graph6 if isinstance(g6_string, bytes): g6_string = bytes_to_str(g6_string) elif not isinstance(g6_string, str): raise ValueError('if input format is graph6, then g6_string must be a string') n = g6_string.find('\n') if n == -1: n = len(g6_string) ss = g6_string[:n] n, s = length_and_string_from_graph6(ss) m = binary_string_from_graph6(s, n) expected = n*(n-1)//2 + (6 - n*(n-1)//2)%6 if len(m) > expected: raise RuntimeError("the string (%s) seems corrupt: for n = %d, the string is too long"%(ss, n)) elif len(m) < expected: raise RuntimeError("the string (%s) seems corrupt: for n = %d, the string is too short"%(ss, n)) G.add_vertices(range(n)) k = 0 for i in range(n): for j in range(i): if m[k] == '1': G._backend.add_edge(i, j, None, False) k += 1
def from_dig6(G, dig6_string): r""" Fill ``G`` with the data of a dig6 string. INPUT: - ``G`` -- a graph - ``dig6_string`` -- a dig6 string EXAMPLES:: sage: from sage.graphs.graph_input import from_dig6 sage: g = DiGraph() sage: from_dig6(g, digraphs.Circuit(10).dig6_string()) sage: g.is_isomorphic(digraphs.Circuit(10)) True """ from .generic_graph_pyx import length_and_string_from_graph6, binary_string_from_dig6 if isinstance(dig6_string, bytes): dig6_string = bytes_to_str(dig6_string) elif not isinstance(dig6_string, str): raise ValueError('if input format is dig6, then dig6_string must be a string') n = dig6_string.find('\n') if n == -1: n = len(dig6_string) ss = dig6_string[:n] n, s = length_and_string_from_graph6(ss) m = binary_string_from_dig6(s, n) expected = n**2 if len(m) > expected: raise RuntimeError("the string (%s) seems corrupt: for n = %d, the string is too long"%(ss, n)) elif len(m) < expected: raise RuntimeError("the string (%s) seems corrupt: for n = %d, the string is too short"%(ss, n)) G.add_vertices(range(n)) k = 0 for i in range(n): for j in range(n): if m[k] == '1': G._backend.add_edge(i, j, None, True) k += 1
def is_jvm_available(self): """ Returns True if the Java Virtual Machine is available and False if not. EXAMPLES: Check that it returns a boolean:: sage: from sage.interfaces.jmoldata import JmolData sage: JData = JmolData() sage: type(JData.is_jvm_available()) <... 'bool'> """ try: version = bytes_to_str( subprocess.check_output(['java', '-version'], stderr=subprocess.STDOUT)) except (subprocess.CalledProcessError, OSError): return False java_version = re.search('version.*([1][.][789]|"\d+")', version) return java_version is not None
def from_sparse6(G, g6_string): r""" Fill ``G`` with the data of a sparse6 string. INPUT: - ``G`` -- a graph - ``g6_string`` -- a sparse6 string EXAMPLES:: sage: from sage.graphs.graph_input import from_sparse6 sage: g = Graph() sage: from_sparse6(g, ':I`ES@obGkqegW~') sage: g.is_isomorphic(graphs.PetersenGraph()) True """ from .generic_graph_pyx import length_and_string_from_graph6, int_to_binary_string if isinstance(g6_string, bytes): g6_string = bytes_to_str(g6_string) elif not isinstance(g6_string, str): raise ValueError( 'if input format is graph6, then g6_string must be a string') n = g6_string.find('\n') if n == -1: n = len(g6_string) s = g6_string[:n] n, s = length_and_string_from_graph6(s[1:]) if not n: edges = [] else: from sage.rings.integer_ring import ZZ k = int((ZZ(n) - 1).nbits()) ords = [ord(i) for i in s] if any(o > 126 or o < 63 for o in ords): raise RuntimeError( "the string seems corrupt: valid characters are \n" + ''.join([chr(i) for i in range(63, 127)])) bits = ''.join([int_to_binary_string(o - 63).zfill(6) for o in ords]) if not k: b = [int(x) for x in bits] x = [0] * len(b) else: b = [] x = [] for i in range(0, len(bits) - k, k + 1): b.append(int(bits[i:i + 1], 2)) x.append(int(bits[i + 1:i + k + 1], 2)) v = 0 edges = [] for i in range(len(b)): v += b[i] # +1 if b[i] == 1 else 0 if x[i] > v: v = x[i] else: if v < n: edges.append((x[i], v)) G.add_vertices(range(n)) G.add_edges(edges)
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 # optional - latte_int 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 # optional - latte_int 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 # optional - latte_int 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 # optional - latte_int 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 # optional - latte_int 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 # optional - latte_int 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 # optional - latte_int 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 ... Testing the runtime error:: sage: P = Polyhedron(rays=[[1,0],[0,1]]) sage: P._volume_latte() # optional - latte_int Traceback (most recent call last): ... RuntimeError: LattE integrale program failed (exit code -6): This is LattE integrale ... ... determinant: nonsquare matrix """ # Check that LattE is present Latte().require() arg = str_to_bytes(arg) from sage.rings.rational import Rational 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, str): # 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'] # 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)) ans, err = latte_proc.communicate(arg) if err: err = bytes_to_str(err) 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 = bytes_to_str(ans) ans = ans.splitlines() ans = ans[-5].split() assert (ans[0] == 'Answer:') ans = ans[1] if raw_output: return ans else: 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 # optional - latte_int 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[2]^(-1))*(1-x[0]^(-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[1]^(-1))*(1-x[0]^(-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[2]^(-1))*(1-x[1]^(-1))*(1-x[0]^(-1))) + x[0]^(-2)*x[1]^2*x[2]^2/((1-x[0])*(1-x[2]^(-1))*(1-x[1]^(-1))) TESTS: Testing raw output:: sage: from sage.interfaces.latte import count # optional - latte_int 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 Testing the runtime error:: sage: P = Polyhedron(rays=[[0,1], [1,0]]) sage: cddin = P.cdd_Hrepresentation() sage: count(cddin, cdd=True, raw_output=False) # optional - latte_int Traceback (most recent call last): ... RuntimeError: LattE integrale program failed (exit code 1): This is LattE integrale ... ... The polyhedron is unbounded. """ # Check that LattE is present Latte().require() arg = str_to_bytes(arg) 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(bytes_to_str(arg)) args += [filename] else: args += ['/dev/stdin'] # 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)) ans, err = latte_proc.communicate(arg) if err: err = bytes_to_str(err) 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 = bytes_to_str(ans) 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: return Integer(ans)
def __call__(self, action, input=None, options=[], verbose=False): r""" This function calls Frobby as a command line program using streams for input and output. Strings passed as part of the command get broken up at whitespace. This is not done to the data passed via the streams. INPUT: - action -- A string telling Frobby what to do. - input -- None or a string that is passed to Frobby as standard in. - options -- A list of options without the dash in front. - verbose -- bool (default: false) Print detailed information. OUTPUT: - string -- What Frobby wrote to the standard output stream. EXAMPLES: We compute the lcm of an ideal provided in Monos format. :: sage: frobby("analyze", input="vars x,y,z;[x^2,x*y];", # optional - frobby ....: options=["lcm", "iformat monos", "oformat 4ti2"]) # optional - frobby ' 2 1 0\n\n2 generators\n3 variables\n' We get an exception if frobby reports an error. :: sage: frobby("do_dishes") # optional - frobby Traceback (most recent call last): ... RuntimeError: Frobby reported an error: ERROR: No action has the prefix "do_dishes". AUTHOR: - Bjarke Hammersholt Roune (2008-04-27) """ command = ['frobby'] + action.split() for option in options: command += ('-' + option.strip()).split() if verbose: print("Frobby action: ", action) print("Frobby options: ", repr(options)) print("Frobby command: ", repr(command)) print("Frobby input:\n", input) process = Popen(command, stdin=PIPE, stdout=PIPE, stderr=PIPE) if input: frinput = str_to_bytes(input) else: frinput = None output, err = process.communicate(input=frinput) output = bytes_to_str(output) err = bytes_to_str(err) if verbose: print("Frobby output:\n", output) print("Frobby error:\n", err) if process.poll() != 0: raise RuntimeError("Frobby reported an error:\n" + err) return output
def load(filename, globals, attach=False): r""" Executes a file in the scope given by ``globals``. If the name starts with ``http://``, it is treated as a URL and downloaded. .. NOTE:: For Cython files, the situation is more complicated -- the module is first compiled to a temporary module ``t`` and executed via:: from t import * INPUT: - ``filename`` -- a string denoting a filename or URL. - ``globals`` -- a string:object dictionary; the context in which to execute the file contents. - ``attach`` -- a boolean (default: False); whether to add the file to the list of attached files. EXAMPLES: Note that ``.py`` files are *not* preparsed:: sage: t = tmp_filename(ext='.py') sage: with open(t, 'w') as f: ....: _ = f.write("print(('hi', 2^3)); z = -2^7") sage: z = 1 sage: sage.repl.load.load(t, globals()) ('hi', 1) sage: z -7 A ``.sage`` file *is* preparsed:: sage: t = tmp_filename(ext='.sage') sage: with open(t, 'w') as f: ....: _ = f.write("print(('hi', 2^3)); z = -2^7") sage: z = 1 sage: sage.repl.load.load(t, globals()) ('hi', 8) sage: z -128 Cython files are *not* preparsed:: sage: t = tmp_filename(ext='.pyx') sage: with open(t, 'w') as f: ....: _ = f.write("print(('hi', 2^3)); z = -2^7") sage: z = 1 sage: sage.repl.load.load(t, globals()) Compiling ... ('hi', 1) sage: z -7 If the file isn't a Cython, Python, or a Sage file, a ValueError is raised:: sage: sage.repl.load.load(tmp_filename(ext=".foo"), globals()) Traceback (most recent call last): ... ValueError: unknown file extension '.foo' for load or attach (supported extensions: .py, .pyx, .sage, .spyx, .f, .f90, .m) We load a file given at a remote URL:: sage: sage.repl.load.load('http://wstein.org/loadtest.py', globals()) # optional - internet hi from the net 5 We can load files using secure http (https):: sage: sage.repl.load.load('https://github.com/jasongrout/minimum_rank/raw/minimum_rank_1_0_0/minrank.py', globals()) # optional - internet We attach a file:: sage: t = tmp_filename(ext='.py') sage: with open(t, 'w') as f: ....: _ = f.write("print('hello world')") sage: sage.repl.load.load(t, globals(), attach=True) hello world sage: t in attached_files() True You can't attach remote URLs (yet):: sage: sage.repl.load.load('http://wstein.org/loadtest.py', globals(), attach=True) # optional - internet Traceback (most recent call last): ... NotImplementedError: you can't attach a URL The default search path for loading and attaching files is the current working directory, i.e., ``'.'``. But you can modify the path with :func:`load_attach_path`:: sage: sage.repl.attach.reset(); reset_load_attach_path() sage: load_attach_path() ['.'] sage: t_dir = tmp_dir() sage: fname = 'test.py' sage: fullpath = os.path.join(t_dir, fname) sage: with open(fullpath, 'w') as f: ....: _ = f.write("print(37 * 3)") sage: load_attach_path(t_dir) sage: attach(fname) 111 sage: sage.repl.attach.reset(); reset_load_attach_path() # clean up or by setting the environment variable ``SAGE_LOAD_ATTACH_PATH`` to a colon-separated list before starting Sage:: $ export SAGE_LOAD_ATTACH_PATH="/path/to/my/library:/path/to/utils" $ sage sage: load_attach_path() # not tested ['.', '/path/to/my/library', '/path/to/utils'] TESTS: Make sure that load handles filenames with spaces in the name or path:: sage: t = tmp_filename(ext=' b.sage') sage: with open(t, 'w') as f: ....: _ = f.write("print(2)") sage: sage.repl.load.load(t, globals()) 2 Non-existing files with spaces give correct messages:: sage: sage.repl.load.load("this file should not exist", globals()) Traceback (most recent call last): ... IOError: did not find file 'this file should not exist' to load or attach """ if attach: from sage.repl.attach import add_attached_file if isinstance(filename, bytes): # For Python 3 in particular, convert bytes filenames to str since the # rest of this functions operate on filename as a str filename = bytes_to_str(filename, FS_ENCODING, 'surrogateescape') filename = os.path.expanduser(filename) if filename.lower().startswith(('http://', 'https://')): if attach: # But see https://en.wikipedia.org/wiki/HTTP_ETag for how # we will do this. # http://www.diveintopython.net/http_web_services/etags.html raise NotImplementedError("you can't attach a URL") from sage.misc.remote_file import get_remote_file filename = get_remote_file(filename, verbose=False) from sage.repl.attach import load_attach_path for path in load_attach_path(): fpath = os.path.join(path, filename) fpath = os.path.expanduser(fpath) if os.path.isfile(fpath): break else: raise IOError('did not find file %r to load or attach' % filename) ext = os.path.splitext(fpath)[1].lower() if ext == '.py': if attach: add_attached_file(fpath) with open(fpath) as f: code = compile(f.read(), fpath, 'exec') exec(code, globals) elif ext == '.sage': from sage.repl.attach import load_attach_mode from sage.repl.preparse import preparse_file_named, preparse_file load_debug_mode, attach_debug_mode = load_attach_mode() if (attach and attach_debug_mode) or ((not attach) and load_debug_mode): # Preparse to a file to enable tracebacks with # code snippets. Use preparse_file_named to make # the file name appear in the traceback as well. # See Trac 11812. if attach: add_attached_file(fpath) with open(preparse_file_named(fpath)) as f: code = compile(f.read(), preparse_file_named(fpath), 'exec') exec(code, globals) else: # Preparse in memory only for speed. if attach: add_attached_file(fpath) with open(fpath) as f: exec(preparse_file(f.read()) + "\n", globals) elif ext == '.spyx' or ext == '.pyx': if attach: add_attached_file(fpath) exec(load_cython(fpath), globals) elif ext == '.f' or ext == '.f90': from sage.misc.inline_fortran import fortran with open(fpath) as f: fortran(f.read(), globals) elif ext == '.m': # Assume magma for now, though maybe .m is used by maple and # mathematica too, and we should really analyze the file # further. s = globals['magma'].load(fpath) i = s.find('\n'); s = s[i+1:] print(s) else: raise ValueError('unknown file extension %r for load or attach (supported extensions: .py, .pyx, .sage, .spyx, .f, .f90, .m)' % ext)
def load(filename, globals, attach=False): r""" Execute a file in the scope given by ``globals``. If the name starts with ``http://`` or ``https://``, it is treated as a URL and downloaded. .. NOTE:: For Cython files, the situation is more complicated -- the module is first compiled to a temporary module ``t`` and executed via:: from t import * INPUT: - ``filename`` -- a string denoting a filename or URL. - ``globals`` -- a string:object dictionary; the context in which to execute the file contents. - ``attach`` -- a boolean (default: False); whether to add the file to the list of attached files. Loading an executable Sage script from the command prompt will run whatever code is inside an if __name__ == "__main__": section, as the condition on ``__name__`` will hold true (code run from the command prompt is considered to be running in the ``__main__`` module.) EXAMPLES: Note that ``.py`` files are *not* preparsed:: sage: t = tmp_filename(ext='.py') sage: with open(t, 'w') as f: ....: _ = f.write("print(('hi', 2^3)); z = -2^7") sage: z = 1 sage: sage.repl.load.load(t, globals()) ('hi', 1) sage: z -7 A ``.sage`` file *is* preparsed:: sage: t = tmp_filename(ext='.sage') sage: with open(t, 'w') as f: ....: _ = f.write("print(('hi', 2^3)); z = -2^7") sage: z = 1 sage: sage.repl.load.load(t, globals()) ('hi', 8) sage: z -128 Cython files are *not* preparsed:: sage: t = tmp_filename(ext='.pyx') sage: with open(t, 'w') as f: ....: _ = f.write("print(('hi', 2^3)); z = -2^7") sage: z = 1 sage: sage.repl.load.load(t, globals()) Compiling ... ('hi', 1) sage: z -7 If the file is not a Cython, Python, or Sage file, a ``ValueError`` is raised:: sage: sage.repl.load.load(tmp_filename(ext=".foo"), globals()) Traceback (most recent call last): ... ValueError: unknown file extension '.foo' for load or attach (supported extensions: .py, .pyx, .sage, .spyx, .f, .f90, .m) We load a file given at a remote URL (not tested for security reasons):: sage: sage.repl.load.load('https://www.sagemath.org/files/loadtest.py', globals()) # not tested hi from the net 5 We can load files using secure http (https):: sage: sage.repl.load.load('https://raw.githubusercontent.com/sagemath/sage-patchbot/3.0.0/sage_patchbot/util.py', globals()) # optional - internet We attach a file:: sage: t = tmp_filename(ext='.py') sage: with open(t, 'w') as f: ....: _ = f.write("print('hello world')") sage: sage.repl.load.load(t, globals(), attach=True) hello world sage: t in attached_files() True You cannot attach remote URLs (yet):: sage: sage.repl.load.load('https://www.sagemath.org/files/loadtest.py', globals(), attach=True) # optional - internet Traceback (most recent call last): ... NotImplementedError: you cannot attach a URL The default search path for loading and attaching files is the current working directory, i.e., ``'.'``. But you can modify the path with :func:`load_attach_path`:: sage: sage.repl.attach.reset(); reset_load_attach_path() sage: load_attach_path() ['.'] sage: t_dir = tmp_dir() sage: fname = 'test.py' sage: fullpath = os.path.join(t_dir, fname) sage: with open(fullpath, 'w') as f: ....: _ = f.write("print(37 * 3)") sage: load_attach_path(t_dir, replace=True) sage: attach(fname) 111 sage: sage.repl.attach.reset(); reset_load_attach_path() # clean up or by setting the environment variable ``SAGE_LOAD_ATTACH_PATH`` to a colon-separated list before starting Sage:: $ export SAGE_LOAD_ATTACH_PATH="/path/to/my/library:/path/to/utils" $ sage sage: load_attach_path() # not tested ['.', '/path/to/my/library', '/path/to/utils'] TESTS: Make sure that load handles filenames with spaces in the name or path:: sage: t = tmp_filename(ext=' b.sage') sage: with open(t, 'w') as f: ....: _ = f.write("print(2)") sage: sage.repl.load.load(t, globals()) 2 Non-existing files with spaces give correct messages:: sage: sage.repl.load.load("this file should not exist", globals()) Traceback (most recent call last): ... OSError: did not find file 'this file should not exist' to load or attach """ if attach: from sage.repl.attach import add_attached_file if isinstance(filename, bytes): # For Python 3 in particular, convert bytes filenames to str since the # rest of this functions operate on filename as a str filename = bytes_to_str(filename, FS_ENCODING, 'surrogateescape') filename = os.path.expanduser(filename) if filename.lower().startswith(('http://', 'https://')): if attach: # But see https://en.wikipedia.org/wiki/HTTP_ETag for how # we will do this. # http://www.diveintopython.net/http_web_services/etags.html raise NotImplementedError("you cannot attach a URL") from sage.misc.remote_file import get_remote_file filename = get_remote_file(filename, verbose=False) from sage.repl.attach import load_attach_path for path in load_attach_path(): fpath = os.path.join(path, filename) fpath = os.path.expanduser(fpath) if os.path.isfile(fpath): break else: raise IOError('did not find file %r to load or attach' % filename) ext = os.path.splitext(fpath)[1].lower() if ext == '.py': if attach: add_attached_file(fpath) with open(fpath) as f: code = compile(f.read(), fpath, 'exec') exec(code, globals) elif ext == '.sage': from sage.repl.attach import load_attach_mode from sage.repl.preparse import preparse_file_named, preparse_file load_debug_mode, attach_debug_mode = load_attach_mode() if (attach and attach_debug_mode) or ((not attach) and load_debug_mode): # Preparse to a file to enable tracebacks with # code snippets. Use preparse_file_named to make # the file name appear in the traceback as well. # See Trac 11812. if attach: add_attached_file(fpath) with open(preparse_file_named(fpath)) as f: code = compile(f.read(), preparse_file_named(fpath), 'exec') exec(code, globals) else: # Preparse in memory only for speed. if attach: add_attached_file(fpath) with open(fpath) as f: exec(preparse_file(f.read()) + "\n", globals) elif ext == '.spyx' or ext == '.pyx': if attach: add_attached_file(fpath) exec(load_cython(fpath), globals) elif ext == '.f' or ext == '.f90': from sage.misc.inline_fortran import fortran with open(fpath) as f: fortran(f.read(), globals) elif ext == '.m': # Assume magma for now, though maybe .m is used by maple and # mathematica too, and we should really analyze the file # further. s = globals['magma'].load(fpath) i = s.find('\n') print(s[i + 1:]) else: raise ValueError('unknown file extension %r for load or attach (supported extensions: .py, .pyx, .sage, .spyx, .f, .f90, .m)' % ext)
def best_linear_code_in_codetables_dot_de(n, k, F, verbose=False): r""" Return the best linear code and its construction as per the web database http://www.codetables.de/ INPUT: - ``n`` - Integer, the length of the code - ``k`` - Integer, the dimension of the code - ``F`` - Finite field, of order 2, 3, 4, 5, 7, 8, or 9 - ``verbose`` - Bool (default: ``False``) OUTPUT: - An unparsed text explaining the construction of the code. EXAMPLES:: sage: L = codes.databases.best_linear_code_in_codetables_dot_de(72, 36, GF(2)) # optional - internet sage: print(L) # optional - internet Construction of a linear code [72,36,15] over GF(2): [1]: [73, 36, 16] Cyclic Linear Code over GF(2) CyclicCode of length 73 with generating polynomial x^37 + x^36 + x^34 + x^33 + x^32 + x^27 + x^25 + x^24 + x^22 + x^21 + x^19 + x^18 + x^15 + x^11 + x^10 + x^8 + x^7 + x^5 + x^3 + 1 [2]: [72, 36, 15] Linear Code over GF(2) Puncturing of [1] at 1 <BLANKLINE> last modified: 2002-03-20 This function raises an ``IOError`` if an error occurs downloading data or parsing it. It raises a ``ValueError`` if the ``q`` input is invalid. AUTHORS: - Steven Sivek (2005-11-14) - David Joyner (2008-03) """ from urllib.request import urlopen from sage.cpython.string import bytes_to_str q = F.order() if not q in [2, 3, 4, 5, 7, 8, 9]: raise ValueError("q (=%s) must be in [2,3,4,5,7,8,9]" % q) n = int(n) k = int(k) param = ("?q=%s&n=%s&k=%s" % (q, n, k)).replace('L', '') url = "http://www.codetables.de/" + "BKLC/BKLC.php" + param if verbose: print("Looking up the bounds at %s" % url) with urlopen(url) as f: s = f.read() s = bytes_to_str(s) i = s.find("<PRE>") j = s.find("</PRE>") if i == -1 or j == -1: raise IOError("Error parsing data (missing pre tags).") return s[i + 5:j].strip()
def _execute(self, query, values=None, silent=None, values_list=False, template=None, commit=None, slow_note=None, reissued=False, buffered=False): """ Execute an SQL command, properly catching errors and returning the resulting cursor. INPUT: - ``query`` -- an SQL Composable object, the SQL command to execute. - ``values`` -- values to substitute for %s in the query. Quoting from the documentation for psycopg2 (http://initd.org/psycopg/docs/usage.html#passing-parameters-to-sql-queries): Never, never, NEVER use Python string concatenation (+) or string parameters interpolation (%) to pass variables to a SQL query string. Not even at gunpoint. - ``silent`` -- boolean (default None). If True, don't log a warning for a slow query. If None, allow DelayCommit contexts to control silencing. - ``values_list`` -- boolean (default False). If True, use the ``execute_values`` method, designed for inserting multiple values. - ``template`` -- string, for use with ``values_list`` to insert constant values: for example ``"(%s, %s, 42)"``. See the documentation of ``execute_values`` for more details. - ``commit`` -- boolean (default None). Whether to commit changes on success. The default is to commit unless we are currently in a DelayCommit context. - ``slow_note`` -- a tuple for generating more useful data for slow query logging. - ``reissued`` -- used internally to prevent infinite recursion when attempting to reset the connection. - ``buffered`` -- whether to create a server side cursor that must be manually closed and connection committed (to closed the transaction) after using it, this implies ``commit=False``. .. NOTE: If the Postgres connection has been closed, the execute statement will fail. We try to recover gracefully by attempting to open a new connection and issuing the command again. However, this approach is not prudent if this execute statement is one of a chain of statements, which we detect by checking whether ``commit == False``. In this case, we will reset the connection but reraise the interface error. The upshot is that you should use ``commit=False`` even for the last of a chain of execute statements, then explicitly call ``self.conn.commit()`` afterward. OUTPUT: - a cursor object from which the resulting records can be obtained via iteration. This function will also log slow queries. """ if not isinstance(query, Composable): raise TypeError( "You must use the psycopg2.sql module to execute queries") if buffered: if commit is None: commit = False elif commit: raise ValueError("buffered and commit are incompatible") try: cur = self._db.cursor(buffered=buffered) t = time.time() if values_list: if template is not None: template = template.as_string(self.conn) execute_values(cur, query.as_string(self.conn), values, template) else: try: cur.execute(query, values) except (OperationalError, ProgrammingError, NotSupportedError, DataError, SyntaxError) as e: try: context = " happens while executing {}".format( cur.mogrify(query, values)) except Exception: context = " happens while executing {} with values {}".format( query, values) reraise(type(e), type(e)(str(e) + context), sys.exc_info()[2]) if silent is False or (silent is None and not self._db._silenced): t = time.time() - t if t > self.slow_cutoff: if values_list: query = query.as_string(self.conn).replace( "%s", "VALUES_LIST") elif values: try: query = cur.mogrify(query, values) except Exception: # This shouldn't happen since the execution above was successful query = query + str(values) else: query = query.as_string(self.conn) self.logger.info( bytes_to_str(query) + " ran in \033[91m {0!s}s \033[0m".format(t)) if slow_note is not None: self.logger.info( "Replicate with db.%s.%s(%s)", slow_note[0], slow_note[1], ", ".join(str(c) for c in slow_note[2:]), ) except (DatabaseError, InterfaceError): if self.conn.closed != 0: # If reissued, we need to raise since we're recursing. if reissued: raise # Attempt to reset the connection self._db.reset_connection() if commit or (commit is None and self._db._nocommit_stack == 0): return self._execute( query, values=values, silent=silent, values_list=values_list, template=template, commit=commit, slow_note=slow_note, buffered=buffered, reissued=True, ) else: raise else: self.conn.rollback() raise else: if commit or (commit is None and self._db._nocommit_stack == 0): self.conn.commit() return cur