Commits

Volker Braun  committed 4426ebc

finished finitely presented groups

  • Participants
  • Parent commits a98e820

Comments (0)

Files changed (12)

File 13681_sagelib.patch

-# HG changeset patch
-# User Jeroen Demeyer <jdemeyer@cage.ugent.be>
-# Date 1351972010 -3600
-# Node ID 12f48e5fe23d178a11d305e33a70917bcceaf93d
-# Parent  ac04c0a5230b1925f81c980d54b69319ba1100b3
-Use os.path.join() to construct temporary filenames
-
-diff --git a/sage/calculus/calculus.py b/sage/calculus/calculus.py
---- a/sage/calculus/calculus.py
-+++ b/sage/calculus/calculus.py
-@@ -1301,7 +1301,7 @@
-         629/8*e^(-4*t) + 91/8*e^(4*t)
-         sage: p1 = plot(xt,0,1/2,rgbcolor=(1,0,0))
-         sage: p2 = plot(yt,0,1/2,rgbcolor=(0,1,0))
--        sage: (p1+p2).save(SAGE_TMP + "de_plot.png")
-+        sage: (p1+p2).save(os.path.join(SAGE_TMP, "de_plot.png"))
- 
-     Another example::
- 
-diff --git a/sage/combinat/words/morphism.py b/sage/combinat/words/morphism.py
---- a/sage/combinat/words/morphism.py
-+++ b/sage/combinat/words/morphism.py
-@@ -563,7 +563,7 @@
-             <class 'sage.combinat.words.word.FiniteWord_iter_with_caching'>
-             sage: w == loads(dumps(w))
-             True
--            sage: save(w, filename=SAGE_TMP + 'test.sobj')
-+            sage: save(w, filename=os.path.join(SAGE_TMP, 'test.sobj'))
- 
-         One may impose the datatype of the resulting word::
- 
-diff --git a/sage/geometry/polytope.py b/sage/geometry/polytope.py
---- a/sage/geometry/polytope.py
-+++ b/sage/geometry/polytope.py
-@@ -50,7 +50,7 @@
- if os.path.exists(path):
-     os.environ['PATH'] = '%s:'%path + os.environ['PATH']
- 
--tmp_file = '%s/tmp.poly'%SAGE_TMP
-+tmp_file = os.path.join(SAGE_TMP, 'tmp.poly')
- 
- class Polytope(SageObject):
-     """
-diff --git a/sage/graphs/bipartite_graph.py b/sage/graphs/bipartite_graph.py
---- a/sage/graphs/bipartite_graph.py
-+++ b/sage/graphs/bipartite_graph.py
-@@ -202,7 +202,7 @@
- 
-     5. From an alist file::
- 
--         sage: file_name = SAGE_TMP + 'deleteme.alist.txt'
-+         sage: file_name = os.path.join(SAGE_TMP, 'deleteme.alist.txt')
-          sage: fi = open(file_name, 'w')
-          sage: fi.write("7 4 \n 3 4 \n 3 3 1 3 1 1 1 \n 3 3 3 4 \n\
-                          1 2 4 \n 1 3 4 \n 1 0 0 \n 2 3 4 \n\
-@@ -903,7 +903,7 @@
- 
-         EXAMPLE::
- 
--            sage: file_name = SAGE_TMP + 'deleteme.alist.txt'
-+            sage: file_name = os.path.join(SAGE_TMP, 'deleteme.alist.txt')
-             sage: fi = open(file_name, 'w')
-             sage: fi.write("7 4 \n 3 4 \n 3 3 1 3 1 1 1 \n 3 3 3 4 \n\
-                             1 2 4 \n 1 3 4 \n 1 0 0 \n 2 3 4 \n\
-@@ -999,7 +999,7 @@
-             [0 1 0 1 0 1 0]
-             [1 1 0 1 0 0 1]
-             sage: b = BipartiteGraph(M)
--            sage: file_name = SAGE_TMP + 'deleteme.alist.txt'
-+            sage: file_name = os.path.join(SAGE_TMP, 'deleteme.alist.txt')
-             sage: b.save_afile(file_name)
-             sage: b2 = BipartiteGraph(file_name)
-             sage: b == b2
-@@ -1007,7 +1007,7 @@
- 
-         TESTS::
- 
--            sage: file_name = SAGE_TMP + 'deleteme.alist.txt'
-+            sage: file_name = os.path.join(SAGE_TMP, 'deleteme.alist.txt')
-             sage: for order in range(3, 13, 3):
-             ...       num_chks = int(order / 3)
-             ...       num_vars = order - num_chks
-diff --git a/sage/gsl/ode.pyx b/sage/gsl/ode.pyx
---- a/sage/gsl/ode.pyx
-+++ b/sage/gsl/ode.pyx
-@@ -226,7 +226,7 @@
-         sage: T.function=f_1
-         sage: T.jacobian=j_1
-         sage: T.ode_solve(y_0=[1,0],t_span=[0,100],params=[10.0],num_points=1000)
--        sage: outfile = SAGE_TMP + 'sage.png'
-+        sage: outfile = os.path.join(SAGE_TMP, 'sage.png')
-         sage: T.plot_solution(filename=outfile)
-         
-     The solver line is equivalent to::
-@@ -316,7 +316,7 @@
-         sage: vander = van_der_pol()               # not tested
-         sage: T.function=vander                    # not tested
-         sage: T.ode_solve(y_0 = [1,0], t_span=[0,2000], num_points=1000)   # not tested
--        sage: T.plot_solution(i=0, filename=SAGE_TMP + '/test.png')        # not tested
-+        sage: T.plot_solution(i=0, filename=os.path.join(SAGE_TMP, 'test.png'))        # not tested
- 
- 
-     """
-diff --git a/sage/interfaces/cleaner.py b/sage/interfaces/cleaner.py
---- a/sage/interfaces/cleaner.py
-+++ b/sage/interfaces/cleaner.py
-@@ -15,16 +15,16 @@
- import os
- 
- import sage.misc.misc as misc
--F = '%s/spawned_processes'%misc.SAGE_TMP
- 
- def cleaner(pid, cmd=''):
-     if cmd != '':
-         cmd = cmd.strip().split()[0]
-     # This is safe, since only this process writes to this file.
-+    F = os.path.join(misc.SAGE_TMP, 'spawned_processes')
-     if os.path.exists(F):
-         o = open(F,'a')
-     else:
--        if not os.path.exists(misc.SAGE_TMP):
-+        if not os.path.exists(str(misc.SAGE_TMP)):
-             return
-         o = open(F,'w')
-     o.write('%s %s\n'%(pid, cmd))
-diff --git a/sage/interfaces/expect.py b/sage/interfaces/expect.py
---- a/sage/interfaces/expect.py
-+++ b/sage/interfaces/expect.py
-@@ -72,21 +72,6 @@
- 
- failed_to_start = []
- 
--#tmp_expect_interface_local='%s/tmp'%SAGE_TMP_INTERFACE
--
--#def tmp_expect_interface_local():
--#    return '%s/tmp'%SAGE_TMP_INTERFACE + str(os.getpid())
--
--## On some platforms, e.g., windows, this can easily take 10 seconds!?!  Terrible.  And
--## it should not be necessary or used anyways. 
--## def _absolute(cmd):
--##     c = cmd.split()
--##     s  = c[0]
--##     t = os.popen('which %s'%s).read().strip()
--##     if len(t) == 0:
--##         raise RuntimeError
--##     return ' '.join([t] + c[1:])
--
- # The subprocess is a shared resource.  In a multi-threaded
- # environment, there would have to be a lock to control access to the
- # subprocess.  Fortunately, Sage does not use Python threads.
-@@ -613,11 +598,10 @@
-         - Simon King (2010-09): Making the tmp-file unique for the interface instance
- 
-         """
--        #return '%s/tmp'%SAGE_TMP_INTERFACE + str(self.pid())
-         try:
-             return self.__local_tmpfile
-         except AttributeError:
--            self.__local_tmpfile = '%s/tmp'%SAGE_TMP_INTERFACE + str(self.pid())
-+            self.__local_tmpfile = os.path.join(SAGE_TMP_INTERFACE, 'tmp' + str(self.pid()))
-             return self.__local_tmpfile
- 
-     def _remote_tmpdir(self):
-diff --git a/sage/interfaces/gap.py b/sage/interfaces/gap.py
---- a/sage/interfaces/gap.py
-+++ b/sage/interfaces/gap.py
-@@ -1026,7 +1026,7 @@
-         workspace file contains more than 82 characters) is fixed::
- 
-             sage: ORIGINAL_WORKSPACE = sage.interfaces.gap.WORKSPACE
--            sage: sage.interfaces.gap.WORKSPACE = SAGE_TMP + "gap" + "0"*(80-len(SAGE_TMP))
-+            sage: sage.interfaces.gap.WORKSPACE = os.path.join(SAGE_TMP, "gap" + "0"*(80-len(SAGE_TMP)))
-             sage: gap = Gap()
-             sage: gap('3+2')
-             5
-diff --git a/sage/interfaces/gnuplot.py b/sage/interfaces/gnuplot.py
---- a/sage/interfaces/gnuplot.py
-+++ b/sage/interfaces/gnuplot.py
-@@ -176,7 +176,7 @@
- 
-     def interact(self, cmd):
-         from sage.misc.all import SAGE_TMP
--        file= '%s/gnuplot'%SAGE_TMP
-+        file = os.path.join(SAGE_TMP, 'gnuplot')
-         open(file, 'w').write(cmd + '\n pause -1 "Press return to continue (no further rotation possible)"')
-         os.system('sage-native-execute gnuplot -persist %s'%file)
- 
-diff --git a/sage/interfaces/magma.py b/sage/interfaces/magma.py
---- a/sage/interfaces/magma.py
-+++ b/sage/interfaces/magma.py
-@@ -1001,9 +1001,10 @@
-         
-         EXAMPLES::
-         
--            sage: open(SAGE_TMP + 'a.m','w').write('function f(n) return n^2; end function;\nprint "hi";')
--            sage: print magma.load(SAGE_TMP + 'a.m')      # optional - magma
--            Loading ".../.sage//temp/.../a.m"
-+            sage: filename = os.path.join(SAGE_TMP, 'a.m')
-+            sage: open(filename, 'w').write('function f(n) return n^2; end function;\nprint "hi";')
-+            sage: print magma.load(filename)      # optional - magma
-+            Loading ".../tmp/.../a.m"
-             hi
-             sage: magma('f(12)')       # optional - magma
-             144
-diff --git a/sage/libs/mwrank/mwrank.pyx b/sage/libs/mwrank/mwrank.pyx
---- a/sage/libs/mwrank/mwrank.pyx
-+++ b/sage/libs/mwrank/mwrank.pyx
-@@ -117,8 +117,7 @@
- 
-         sage: from sage.libs.mwrank.mwrank import get_precision
-         sage: get_precision()
--	50
--
-+        50
-     """
-     return mwrank_get_precision()
- 
-@@ -154,7 +153,7 @@
- 
-     EXAMPLES::
- 
--        sage: file= SAGE_TMP + '/PRIMES'
-+        sage: file = os.path.join(SAGE_TMP, 'PRIMES')
-         sage: open(file,'w').write(' '.join([str(p) for p in prime_range(10^7,10^7+20)]))
-         sage: mwrank_initprimes(file, verb=True)
- 
-diff --git a/sage/matrix/matrix2.pyx b/sage/matrix/matrix2.pyx
---- a/sage/matrix/matrix2.pyx
-+++ b/sage/matrix/matrix2.pyx
-@@ -7333,7 +7333,7 @@
-         EXAMPLE::
-         
-             sage: M = random_matrix(CC, 4)
--            sage: M.visualize_structure(SAGE_TMP + "matrix.png")
-+            sage: M.visualize_structure(os.path.join(SAGE_TMP, "matrix.png"))
-         """
-         import gd
-         import os
-diff --git a/sage/misc/cython.py b/sage/misc/cython.py
---- a/sage/misc/cython.py
-+++ b/sage/misc/cython.py
-@@ -373,7 +373,7 @@
-     # This is the *temporary* directory where we build the pyx file.
-     # This is deleted when sage exits, which means pyx files must be
-     # rebuilt every time Sage is restarted at present.
--    build_dir = '%s/%s'%(SPYX_TMP, base)
-+    build_dir = os.path.join(SPYX_TMP, base)
- 
-     if os.path.exists(build_dir):
-         # There is already a module here. Maybe we do not have to rebuild?
-diff --git a/sage/misc/dist.py b/sage/misc/dist.py
---- a/sage/misc/dist.py
-+++ b/sage/misc/dist.py
-@@ -70,7 +70,7 @@
- 
-     EXAMPLES::
- 
--        sage: install_scripts(SAGE_TMP, ignore_existing=True)
-+        sage: install_scripts(str(SAGE_TMP), ignore_existing=True)
-         Checking that Sage has the command 'gap' installed
-         ...
-     """
-diff --git a/sage/misc/latex.py b/sage/misc/latex.py
---- a/sage/misc/latex.py
-+++ b/sage/misc/latex.py
-@@ -2112,7 +2112,7 @@
-     EXAMPLES::
- 
-         sage: from sage.misc.latex import png
--        sage: png(ZZ[x], SAGE_TMP + "zz.png") # random - error if no latex
-+        sage: png(ZZ[x], os.path.join(SAGE_TMP, "zz.png")) # random - error if no latex
-     """
-     if not pdflatex:
-         engine = "latex"
-diff --git a/sage/misc/misc.py b/sage/misc/misc.py
---- a/sage/misc/misc.py
-+++ b/sage/misc/misc.py
-@@ -135,15 +135,14 @@
- 
- #################################################
- # Next we create the Sage temporary directory.
--# It is called temp instead of tmp mainly for
--# "historical reasons"...
-+#################################################
- 
- SAGE_TMP = os.path.join(DOT_SAGE, 'tmp', HOSTNAME, str(os.getpid()))
- sage_makedirs(SAGE_TMP)
- 
--SPYX_TMP = os.path.join(SAGE_TMP, 'spyx/')
-+SPYX_TMP = os.path.join(SAGE_TMP, 'spyx')
- 
--SAGE_TMP_INTERFACE = os.path.join(SAGE_TMP, 'interface/')
-+SAGE_TMP_INTERFACE = os.path.join(SAGE_TMP, 'interface')
- sage_makedirs(SAGE_TMP_INTERFACE)
- 
- SAGE_DB = os.path.join(DOT_SAGE, 'db')
-diff --git a/sage/misc/sageinspect.py b/sage/misc/sageinspect.py
---- a/sage/misc/sageinspect.py
-+++ b/sage/misc/sageinspect.py
-@@ -1430,9 +1430,9 @@
-         source_lines = open(filename).readlines()
-     except IOError:
-         try:
--            from sage.all import SAGE_TMP
-+            from sage.misc.misc import SPYX_TMP
-             raw_name = filename.split('/')[-1]
--            newname = SAGE_TMP+'/spyx/'+'_'.join(raw_name.split('_')[:-1])+'/'+raw_name
-+            newname = os.path.join(SPYX_TMP, '_'.join(raw_name.split('_')[:-1]), raw_name)
-             source_lines = open(newname).readlines()
-         except IOError:
-             return None
-diff --git a/sage/misc/session.pyx b/sage/misc/session.pyx
---- a/sage/misc/session.pyx
-+++ b/sage/misc/session.pyx
-@@ -17,11 +17,11 @@
- save your session permanently, since SAGE_TMP will be removed when
- leaving Sage!::
- 
--    sage: save_session(SAGE_TMP+'session')
-+    sage: save_session(os.path.join(SAGE_TMP, 'session'))
- 
- This saves a dictionary with $w$ as one of the keys::
- 
--    sage: z = load(SAGE_TMP+'session')
-+    sage: z = load(os.path.join(SAGE_TMP, 'session'))
-     sage: z.keys()
-     ['w']
-     sage: z['w']
-@@ -32,7 +32,7 @@
-     sage: reset()
-     sage: show_identifiers()
-     []
--    sage: load_session(SAGE_TMP+'session')
-+    sage: load_session(os.path.join(SAGE_TMP, 'session'))
- 
- Indeed $w$ is now defined again.::
- 
-diff --git a/sage/numerical/backends/coin_backend.pyx b/sage/numerical/backends/coin_backend.pyx
---- a/sage/numerical/backends/coin_backend.pyx
-+++ b/sage/numerical/backends/coin_backend.pyx
-@@ -1035,7 +1035,7 @@
-             1
-             sage: p.add_linear_constraint([(0, 1), (1, 2)], None, 3)          # optional - Coin
-             sage: p.set_objective([2, 5])                          # optional - Coin
--            sage: p.write_mps(SAGE_TMP+"/lp_problem.mps", 0)       # optional - Coin
-+            sage: p.write_mps(os.path.join(SAGE_TMP, "lp_problem.mps"), 0)       # optional - Coin
-         """
- 
-         cdef char * mps = "mps"
-@@ -1057,7 +1057,7 @@
-             1
-             sage: p.add_linear_constraint([(0, 1), (1, 2)], None, 3)          # optional - Coin
-             sage: p.set_objective([2, 5])                          # optional - Coin
--            sage: p.write_lp(SAGE_TMP+"/lp_problem.lp")       # optional - Coin
-+            sage: p.write_lp(os.path.join(SAGE_TMP, "lp_problem.lp"))       # optional - Coin
-         """
- 
-         cdef char * lp = "lp"
-diff --git a/sage/numerical/backends/cplex_backend.pyx b/sage/numerical/backends/cplex_backend.pyx
---- a/sage/numerical/backends/cplex_backend.pyx
-+++ b/sage/numerical/backends/cplex_backend.pyx
-@@ -1274,7 +1274,7 @@
-             1
-             sage: p.add_linear_constraint([(0, 1), (1, 2)], None, 3)          # optional - CPLEX
-             sage: p.set_objective([2, 5])                          # optional - CPLEX
--            sage: p.write_lp(SAGE_TMP+"/lp_problem.lp")            # optional - CPLEX
-+            sage: p.write_lp(os.path.join(SAGE_TMP, "lp_problem.lp"))            # optional - CPLEX
-         """
- 
-         cdef int status
-@@ -1298,7 +1298,7 @@
-             1
-             sage: p.add_linear_constraint([(0, 1), (1, 2)], None, 3)          # optional - CPLEX
-             sage: p.set_objective([2, 5])                          # optional - CPLEX
--            sage: p.write_lp(SAGE_TMP+"/lp_problem.lp")            # optional - CPLEX
-+            sage: p.write_lp(os.path.join(SAGE_TMP, "lp_problem.lp"))            # optional - CPLEX
-         """
- 
-         cdef int status
-diff --git a/sage/numerical/backends/generic_backend.pyx b/sage/numerical/backends/generic_backend.pyx
---- a/sage/numerical/backends/generic_backend.pyx
-+++ b/sage/numerical/backends/generic_backend.pyx
-@@ -554,7 +554,7 @@
-             2
-             sage: p.add_linear_constraint([(0, 1], (1, 2)], None, 3) # optional - Nonexistent_LP_solver
-             sage: p.set_objective([2, 5])                          # optional - Nonexistent_LP_solver
--            sage: p.write_lp(SAGE_TMP+"/lp_problem.lp")            # optional - Nonexistent_LP_solver
-+            sage: p.write_lp(os.path.join(SAGE_TMP, "lp_problem.lp"))            # optional - Nonexistent_LP_solver
-         """
-         raise NotImplementedError()
- 
-@@ -574,7 +574,7 @@
-             2
-             sage: p.add_linear_constraint([(0, 1), (1, 2)], None, 3) # optional - Nonexistent_LP_solver
-             sage: p.set_objective([2, 5])                          # optional - Nonexistent_LP_solver
--            sage: p.write_lp(SAGE_TMP+"/lp_problem.lp")            # optional - Nonexistent_LP_solver
-+            sage: p.write_lp(os.path.join(SAGE_TMP, "lp_problem.lp"))            # optional - Nonexistent_LP_solver
-         """
-         raise NotImplementedError()
- 
-diff --git a/sage/numerical/backends/glpk_backend.pyx b/sage/numerical/backends/glpk_backend.pyx
---- a/sage/numerical/backends/glpk_backend.pyx
-+++ b/sage/numerical/backends/glpk_backend.pyx
-@@ -1211,7 +1211,7 @@
-             1
-             sage: p.add_linear_constraint([[0, 1], [1, 2]], None, 3)
-             sage: p.set_objective([2, 5])
--            sage: p.write_lp(SAGE_TMP+"/lp_problem.lp")
-+            sage: p.write_lp(os.path.join(SAGE_TMP, "lp_problem.lp"))
-         """
-         glp_write_lp(self.lp, NULL, filename)
- 
-@@ -1231,7 +1231,7 @@
-             1
-             sage: p.add_linear_constraint([[0, 1], [1, 2]], None, 3)
-             sage: p.set_objective([2, 5])
--            sage: p.write_lp(SAGE_TMP+"/lp_problem.lp")
-+            sage: p.write_lp(os.path.join(SAGE_TMP, "lp_problem.lp"))
-         """
-         glp_write_mps(self.lp, modern, NULL,  filename)
- 
-diff --git a/sage/numerical/backends/gurobi_backend.pyx b/sage/numerical/backends/gurobi_backend.pyx
---- a/sage/numerical/backends/gurobi_backend.pyx
-+++ b/sage/numerical/backends/gurobi_backend.pyx
-@@ -1101,7 +1101,7 @@
-             1
-             sage: p.add_linear_constraint([[0, 1], [1, 2]], None, 3)                # optional - Gurobi
-             sage: p.set_objective([2, 5])                                           # optional - Gurobi
--            sage: p.write_lp(SAGE_TMP+"/lp_problem.lp")                             # optional - Gurobi
-+            sage: p.write_lp(os.path.join(SAGE_TMP, "lp_problem.lp"))               # optional - Gurobi
-         """
-         check(self.env, GRBwrite(self.model[0], filename))
- 
-@@ -1121,7 +1121,7 @@
-             1
-             sage: p.add_linear_constraint([[0, 1], [1, 2]], None, 3)                # optional - Gurobi
-             sage: p.set_objective([2, 5])                                           # optional - Gurobi
--            sage: p.write_lp(SAGE_TMP+"/lp_problem.lp")                             # optional - Gurobi
-+            sage: p.write_lp(os.path.join(SAGE_TMP, "lp_problem.lp"))               # optional - Gurobi
-         """
-         check(self.env, GRBwrite(self.model[0], filename))
- 
-diff --git a/sage/numerical/mip.pyx b/sage/numerical/mip.pyx
---- a/sage/numerical/mip.pyx
-+++ b/sage/numerical/mip.pyx
-@@ -724,7 +724,7 @@
-             sage: x = p.new_variable()
-             sage: p.set_objective(x[1] + x[2])
-             sage: p.add_constraint(-3*x[1] + 2*x[2], max=2,name="OneConstraint")
--            sage: p.write_mps(SAGE_TMP+"/lp_problem.mps")
-+            sage: p.write_mps(os.path.join(SAGE_TMP, "lp_problem.mps"))
- 
-         For information about the MPS file format :
-         http://en.wikipedia.org/wiki/MPS_%28format%29
-@@ -749,7 +749,7 @@
-             sage: x = p.new_variable()
-             sage: p.set_objective(x[1] + x[2])
-             sage: p.add_constraint(-3*x[1] + 2*x[2], max=2)
--            sage: p.write_lp(SAGE_TMP+"/lp_problem.lp")
-+            sage: p.write_lp(os.path.join(SAGE_TMP, "lp_problem.lp"))
- 
-         For more information about the LP file format :
-         http://lpsolve.sourceforge.net/5.5/lp-format.htm
-diff --git a/sage/plot/plot3d/base.pyx b/sage/plot/plot3d/base.pyx
---- a/sage/plot/plot3d/base.pyx
-+++ b/sage/plot/plot3d/base.pyx
-@@ -1082,7 +1082,7 @@
-         # Tachyon resolution options
-         if DOCTEST_MODE:
-             opts = '-res 10 10'
--            filename = sage.misc.misc.SAGE_TMP + "/tmp"
-+            filename = os.path.join(sage.misc.misc.SAGE_TMP, "tmp")
-         elif EMBEDDED_MODE:
-             opts = '-res %s %s'%(figsize[0]*100, figsize[1]*100)
-             filename = sage.misc.temporary_file.graphics_filename()[:-4]
-diff --git a/sage/plot/plot3d/tachyon.py b/sage/plot/plot3d/tachyon.py
---- a/sage/plot/plot3d/tachyon.py
-+++ b/sage/plot/plot3d/tachyon.py
-@@ -314,7 +314,7 @@
-         import sage.plot.plot
-         if sage.plot.plot.DOCTEST_MODE:
-             filename = graphics_filename()
--            self.save(SAGE_TMP + '/test.png', verbose=verbose, extra_opts=extra_opts)
-+            self.save(os.path.join(SAGE_TMP, 'test.png'), verbose=verbose, extra_opts=extra_opts)
-             return
-         if sage.plot.plot.EMBEDDED_MODE:
-             filename = graphics_filename()
-diff --git a/sage/plot/text.py b/sage/plot/text.py
---- a/sage/plot/text.py
-+++ b/sage/plot/text.py
-@@ -232,7 +232,7 @@
- 
-     You can save text as part of PDF output::
- 
--        sage: text("sage", (0,0), rgbcolor=(0,0,0)).save(SAGE_TMP + 'a.pdf')
-+        sage: text("sage", (0,0), rgbcolor=(0,0,0)).save(os.path.join(SAGE_TMP, 'a.pdf'))
- 
-     Text must be 2D (use the text3d command for 3D text)::
- 
-diff --git a/sage/server/notebook/notebook.py b/sage/server/notebook/notebook.py
---- a/sage/server/notebook/notebook.py
-+++ b/sage/server/notebook/notebook.py
-@@ -1180,7 +1180,7 @@
-         
-         ::
- 
--            sage: savefile = SAGE_TMP + 'tmp.sws'
-+            sage: savefile = os.path.join(SAGE_TMP, 'tmp.sws')
-         
-             sage: nb.export_worksheet(W.filename(),  savefile, verbose=False)
-         
-diff --git a/sage/structure/sage_object.pyx b/sage/structure/sage_object.pyx
---- a/sage/structure/sage_object.pyx
-+++ b/sage/structure/sage_object.pyx
-@@ -185,8 +185,8 @@
-         EXAMPLES::
-         
-             sage: f = x^3 + 5
--            sage: f.save(SAGE_TMP + '/file')
--            sage: load(SAGE_TMP + '/file.sobj')
-+            sage: f.save(os.path.join(SAGE_TMP, 'file'))
-+            sage: load(os.path.join(SAGE_TMP, 'file.sobj'))
-             x^3 + 5
-         """
-         if filename is None:
-@@ -814,8 +814,8 @@
-     EXAMPLES::
-     
-         sage: a = matrix(2, [1,2,3,-5/2])
--        sage: objfile = SAGE_TMP + 'test.sobj'
--        sage: objfile_short = SAGE_TMP + 'test'
-+        sage: objfile = os.path.join(SAGE_TMP, 'test.sobj')
-+        sage: objfile_short = os.path.join(SAGE_TMP, 'test')
-         sage: save(a, objfile)
-         sage: load(objfile_short)
-         [   1    2]
-@@ -823,14 +823,14 @@
-         sage: E = EllipticCurve([-1,0])
-         sage: P = plot(E)
-         sage: save(P, objfile_short)   # saves the plot to "test.sobj"
--        sage: save(P, filename=SAGE_TMP + "sage.png", xmin=-2)
--        sage: save(P, SAGE_TMP + "filename.with.some.wrong.ext")
-+        sage: save(P, filename=os.path.join(SAGE_TMP, "sage.png"), xmin=-2)
-+        sage: save(P, os.path.join(SAGE_TMP, "filename.with.some.wrong.ext"))
-         Traceback (most recent call last):
-         ...
-         ValueError: allowed file extensions for images are '.eps', '.pdf', '.png', '.ps', '.sobj', '.svg'!
-         sage: print load(objfile)
-         Graphics object consisting of 2 graphics primitives
--        sage: save("A python string", SAGE_TMP + 'test')
-+        sage: save("A python string", os.path.join(SAGE_TMP, 'test'))
-         sage: load(objfile)
-         'A python string'
-         sage: load(objfile_short)
-@@ -840,7 +840,7 @@
- 
-     Check that #11577 is fixed::
- 
--        sage: filename = SAGE_TMP + "foo.bar" # filename containing a dot
-+        sage: filename = os.path.join(SAGE_TMP, "foo.bar")  # filename containing a dot
-         sage: save((1,1),filename)            # saves tuple to "foo.bar.sobj"
-         sage: load(filename)
-         (1, 1)
 trac_13211_pool_size.patch
 trac_13211_itanium_fix.patch
 trac_13211_quit_after_workspace.patch
-13681_sagelib.patch
 trac_6391_libGAP.patch
 trac_13588_improve_libGAP.patch
 trac_13687_Parent_for_groups.patch
+trac_13687_review.patch
+trac_13687_assertions.patch
+trac_12407_primitive_permutation_groups.patch
+trac_12407_review.patch
+trac_12339_fpgroups_libgap.patch
+trac_12339_reviewer.patch
 trac_11395_update_gfan.patch
 trac11395-fix_tutorial.patch
 trac_11395_doctest_fix.patch
 trac_9880_revert_marking_random_from_trac_10187.patch #+pynac
 trac_11667_use_groebner_basis_with_degree_bound.patch  #+todo
 trac_11559_fix_Chow_group.patch   #+todo maybe delete
-trac_11763_ZZ_polyhedron.patch          #+todo
 trac_12193_fix_dimension.patch
 trac_12553_ppl_count_points.patch
 trac_12553_ppl_lattice_polytope.patch

File trac_11763_ZZ_polyhedron.patch

-# HG changeset patch
-# Parent c69fd8f38ffcadfec2decc0155b267a6e23498d3
-# HG changeset patch
-# Parent fe5790d3e8b49343e2049d5078055a8ceec9c167
-# HG changeset patch
-# Parent c69fd8f38ffcadfec2decc0155b267a6e23498d3
-# HG changeset patch
-# Parent fe5790d3e8b49343e2049d5078055a8ceec9c167
-
-Trac #11763: Add ZZ as allowed base ring for polyhedra
-
-diff --git a/doc/en/reference/geometry.rst b/doc/en/reference/geometry.rst
---- a/doc/en/reference/geometry.rst
-+++ b/doc/en/reference/geometry.rst
-@@ -25,6 +25,7 @@
-    sage/geometry/polyhedron/plot
-    sage/geometry/polyhedron/base
-    sage/geometry/polyhedron/base_QQ
-+   sage/geometry/polyhedron/base_ZZ
-    sage/geometry/polyhedron/base_RDF
-    sage/geometry/polyhedron/backend_cdd
-    sage/geometry/polyhedron/backend_ppl
-diff --git a/sage/geometry/polyhedron/backend_ppl.py b/sage/geometry/polyhedron/backend_ppl.py
---- a/sage/geometry/polyhedron/backend_ppl.py
-+++ b/sage/geometry/polyhedron/backend_ppl.py
-@@ -11,7 +11,9 @@
-     Variable, Linear_Expression,
-     line, ray, point )
-
-+from base import Polyhedron_base
- from base_QQ import Polyhedron_QQ
-+from base_ZZ import Polyhedron_ZZ
- from representation import (
-     PolyhedronRepresentation,
-     Hrepresentation,
-@@ -22,9 +24,9 @@
-
-
- #########################################################################
--class Polyhedron_QQ_ppl(Polyhedron_QQ):
-+class Polyhedron_ppl(Polyhedron_base):
-     """
--    Polyhedra over `\QQ` with ppl
-+    Polyhedra with ppl
-
-     INPUT:
-
-@@ -63,8 +65,8 @@
-         EXAMPLES::
-
-             sage: p = Polyhedron(backend='ppl')
--            sage: from sage.geometry.polyhedron.backend_ppl import Polyhedron_QQ_ppl
--            sage: Polyhedron_QQ_ppl._init_from_Vrepresentation(p, 2, [], [], [])
-+            sage: from sage.geometry.polyhedron.backend_ppl import Polyhedron_ppl
-+            sage: Polyhedron_ppl._init_from_Vrepresentation(p, 2, [], [], [])
-         """
-         gs = Generator_System()
-         if vertices is None: vertices = []
-@@ -106,8 +108,8 @@
-         EXAMPLES::
-
-             sage: p = Polyhedron(backend='ppl')
--            sage: from sage.geometry.polyhedron.backend_ppl import Polyhedron_QQ_ppl
--            sage: Polyhedron_QQ_ppl._init_from_Hrepresentation(p, 2, [], [])
-+            sage: from sage.geometry.polyhedron.backend_ppl import Polyhedron_ppl
-+            sage: Polyhedron_ppl._init_from_Hrepresentation(p, 2, [], [])
-         """
-         cs = Constraint_System()
-         if ieqs is None: ieqs = []
-@@ -212,7 +214,51 @@
-             The empty polyhedron in QQ^0
-             sage: Polyhedron(backend='ppl')._init_empty_polyhedron(0)
-         """
--        super(Polyhedron_QQ_ppl, self)._init_empty_polyhedron(ambient_dim)
-+        super(Polyhedron_ppl, self)._init_empty_polyhedron(ambient_dim)
-         self._ppl_polyhedron = C_Polyhedron(ambient_dim, 'empty')
-
-
-+
-+
-+#########################################################################
-+class Polyhedron_QQ_ppl(Polyhedron_ppl, Polyhedron_QQ):
-+    """
-+    Polyhedra over `\QQ` with ppl
-+
-+    INPUT:
-+
-+    - ``ambient_dim`` -- integer. The dimension of the ambient space.
-+
-+    - ``Vrep`` -- a list ``[vertices, rays, lines]``.
-+
-+    - ``Hrep`` -- a list ``[ieqs, eqns]``.
-+
-+    EXAMPLES::
-+
-+        sage: p = Polyhedron(vertices=[(0,0),(1,0),(0,1)], rays=[(1,1)], lines=[],
-+        ...                  backend='ppl', base_ring=QQ)
-+        sage: TestSuite(p).run(skip='_test_pickling')
-+    """
-+    pass
-+
-+
-+#########################################################################
-+class Polyhedron_ZZ_ppl(Polyhedron_ppl, Polyhedron_ZZ):
-+    """
-+    Polyhedra over `\ZZ` with ppl
-+
-+    INPUT:
-+
-+    - ``ambient_dim`` -- integer. The dimension of the ambient space.
-+
-+    - ``Vrep`` -- a list ``[vertices, rays, lines]``.
-+
-+    - ``Hrep`` -- a list ``[ieqs, eqns]``.
-+
-+    EXAMPLES::
-+
-+        sage: p = Polyhedron(vertices=[(0,0),(1,0),(0,1)], rays=[(1,1)], lines=[])
-+        ...                  backend='ppl', base_ring=ZZ)
-+        sage: TestSuite(p).run(skip='_test_pickling')
-+    """
-+    pass
-diff --git a/sage/geometry/polyhedron/base.py b/sage/geometry/polyhedron/base.py
---- a/sage/geometry/polyhedron/base.py
-+++ b/sage/geometry/polyhedron/base.py
-@@ -542,9 +542,11 @@
-         else:
-             desc += 'A ' + repr(self.dim()) + '-dimensional polyhedron'
-         desc += ' in '
--        if self.field()==QQ: desc += 'QQ'
--        else:                desc += 'RDF'
--        desc += '^' + repr(self.ambient_dim())
-+        if   self.base_ring() is QQ:  desc += 'QQ'
-+        elif self.base_ring() is ZZ:  desc += 'ZZ'
-+        elif self.base_ring() is RDF: desc += 'RDF'
-+        else: assert False
-+        desc += '^' + repr(self.ambient_dim())
-
-         if self.n_vertices()>0:
-             desc += ' defined as the convex hull of '
-@@ -1356,8 +1358,8 @@
-             sage: poly_test.ambient_space()
-             Vector space of dimension 4 over Rational Field
-         """
--        from sage.modules.free_module import VectorSpace
--        return VectorSpace(self.base_ring(), self.ambient_dim())
-+        from sage.modules.free_module import FreeModule
-+        return FreeModule(self.base_ring(), self.ambient_dim())
-
-     Vrepresentation_space = ambient_space
-
-diff --git a/sage/geometry/polyhedron/base_ZZ.py b/sage/geometry/polyhedron/base_ZZ.py
-new file mode 100644
---- /dev/null
-+++ b/sage/geometry/polyhedron/base_ZZ.py
-@@ -0,0 +1,237 @@
-+"""
-+Base class for polyhedra over `\ZZ`
-+"""
-+
-+########################################################################
-+#       Copyright (C) 2011 Volker Braun <vbraun.name@gmail.com>
-+#
-+#  Distributed under the terms of the GNU General Public License (GPL)
-+#
-+#                  http://www.gnu.org/licenses/
-+########################################################################
-+
-+
-+
-+from sage.rings.all import ZZ, QQ
-+from sage.misc.all import cached_method
-+from sage.matrix.constructor import matrix
-+
-+from constructor import Polyhedron
-+from base import Polyhedron_base
-+
-+
-+
-+#########################################################################
-+class Polyhedron_ZZ(Polyhedron_base):
-+    """
-+    Base class for Polyhedra over `\ZZ`
-+
-+    TESTS::
-+
-+        sage: p = Polyhedron([(0,0)], base_ring=ZZ);  p
-+        A 0-dimensional polyhedron in ZZ^2 defined as the convex hull of 1 vertex
-+        sage: TestSuite(p).run(skip='_test_pickling')
-+    """
-+    def _is_zero(self, x):
-+        """
-+        Test whether ``x`` is zero.
-+
-+        INPUT:
-+
-+        - ``x`` -- a number in the base ring.
-+
-+        OUTPUT:
-+
-+        Boolean.
-+
-+        EXAMPLES::
-+
-+            sage: p = Polyhedron([(0,0)], base_ring=ZZ)
-+            sage: p._is_zero(0)
-+            True
-+            sage: p._is_zero(1/100000)
-+            False
-+        """
-+        return x==0
-+
-+    def _is_nonneg(self, x):
-+        """
-+        Test whether ``x`` is nonnegative.
-+
-+        INPUT:
-+
-+        - ``x`` -- a number in the base ring.
-+
-+        OUTPUT:
-+
-+        Boolean.
-+
-+        EXAMPLES::
-+
-+            sage: p = Polyhedron([(0,0)], base_ring=ZZ)
-+            sage: p._is_nonneg(1)
-+            True
-+            sage: p._is_nonneg(-1/100000)
-+            False
-+        """
-+        return x>=0
-+
-+    def _is_positive(self, x):
-+        """
-+        Test whether ``x`` is positive.
-+
-+        INPUT:
-+
-+        - ``x`` -- a number in the base ring.
-+
-+        OUTPUT:
-+
-+        Boolean.
-+
-+        EXAMPLES::
-+
-+            sage: p = Polyhedron([(0,0)], base_ring=ZZ)
-+            sage: p._is_positive(1)
-+            True
-+            sage: p._is_positive(0)
-+            False
-+        """
-+        return x>0
-+
-+    _base_ring = ZZ
-+
-+    def is_lattice_polytope(self):
-+        r"""
-+        Return whether the polyhedron is a lattice polytope.
-+
-+        OUTPUT:
-+
-+        ``True`` if the polyhedron is compact and has only integral
-+        vertices, ``False`` otherwise.
-+
-+        EXAMPLES::
-+
-+            sage: polytopes.cross_polytope(3).is_lattice_polytope()
-+            True
-+            sage: polytopes.regular_polygon(5).is_lattice_polytope()
-+            False
-+        """
-+        return True
-+
-+    @cached_method
-+    def polar(self):
-+        """
-+        Return the polar (dual) polytope.
-+
-+        The polytope must have the IP-property (see
-+        :meth:`has_IP_property`), that is, the origin must be an
-+        interior point. In particular, it must be full-dimensional.
-+
-+        OUTPUT:
-+
-+        The polytope whose vertices are the coefficient vectors of the
-+        inequalities of ``self`` with inhomogeneous term normalized to
-+        unity.
-+
-+        EXAMPLES::
-+
-+            sage: p = Polyhedron(vertices=[(1,0,0),(0,1,0),(0,0,1),(-1,-1,-1)], base_ring=ZZ)
-+            sage: p.polar()
-+            A 3-dimensional polyhedron in ZZ^3 defined as the convex hull of 4 vertices
-+            sage: type(_)
-+            <class 'sage.geometry.polyhedron.backend_ppl.Polyhedron_ZZ_ppl'>
-+            sage: p.polar().base_ring()
-+            Integer Ring
-+        """
-+        if not self.has_IP_property():
-+            raise ValueError('The polytope must have the IP property.')
-+
-+        vertices = [ ieq.A()/ieq.b() for
-+                     ieq in self.inequality_generator() ]
-+        if all( all(v_i in ZZ for v_i in v) for v in vertices):
-+            return Polyhedron(vertices=vertices, base_ring=ZZ)
-+        else:
-+            return Polyhedron(vertices=vertices, base_ring=QQ)
-+
-+    @cached_method
-+    def is_reflexive(self):
-+        """
-+        EXAMPLES::
-+
-+            sage: p = Polyhedron(vertices=[(1,0,0),(0,1,0),(0,0,1),(-1,-1,-1)], base_ring=ZZ)
-+            sage: p.is_reflexive()
-+            True
-+        """
-+        return self.polar().is_lattice_polytope()
-+
-+    @cached_method
-+    def has_IP_property(self):
-+        """
-+        Test whether the polyhedron has the IP property.
-+
-+        The IP (interior point) property means that
-+
-+        * ``self`` is compact (a polytope).
-+
-+        * ``self`` contains the origin.
-+
-+        This implies that
-+
-+        * ``self`` is full-dimensional.
-+
-+        * The dual polyhedron is again a polytope (that is, a compact
-+          polyhedron), though not necessarily a lattice polytope.
-+
-+        REFERENCES::
-+
-+        ..  [PALP]
-+            Maximilian Kreuzer, Harald Skarke:
-+            "PALP: A Package for Analyzing Lattice Polytopes
-+            with Applications to Toric Geometry"
-+            Comput.Phys.Commun. 157 (2004) 87-106
-+            http://arxiv.org/abs/math/0204356
-+        """
-+        return self.is_compact() and self.contains(self.ambient_space().zero())
-+
-+    def fibrations(self):
-+        """
-+        EXAMPLES::
-+
-+            sage: P = Polyhedron(toric_varieties.P4_11169().fan().rays(), base_ring=ZZ)
-+            sage: list( P.fibrations() )
-+            [A 2-dimensional polyhedron in QQ^4 defined as the convex hull of 3 vertices]
-+        """
-+        if not self.has_IP_property():
-+            raise ValueError('The polytope must have the IP property.')
-+        # todo: just go through pairs of points on the same facet
-+        fiber_dimension = 2
-+        points = self.integral_points()
-+        fibers = set()
-+        for i1 in range(0,len(points)):
-+            p1 = points[i1]
-+            if p1.is_zero():
-+                continue
-+            for i2 in range(i1+1,len(points)):
-+                p2 = points[i2]
-+                if p2.is_zero():
-+                    continue
-+                plane_12 = Polyhedron(lines=[p1,p2])
-+                if plane_12.dim() != 2:
-+                    continue
-+                fiber = self.intersection(plane_12)
-+                if not fiber.is_lattice_polytope():
-+                    continue
-+                fiber_matrix = matrix(ZZ,sorted(fiber.integral_points()))
-+                fiber_matrix.set_immutable()
-+                if fiber_matrix not in fibers:
-+                    yield fiber
-+                    fibers.update([fiber_matrix])
-+
-+
-+
-+
-+
-+
-+
-+
-+
-diff --git a/sage/geometry/polyhedron/constructor.py b/sage/geometry/polyhedron/constructor.py
---- a/sage/geometry/polyhedron/constructor.py
-+++ b/sage/geometry/polyhedron/constructor.py
-@@ -159,8 +159,8 @@
-       * ``'cddf'``: cdd with floating-point coefficients
-
-       * ``'ppl'``: use ppl
--        (:mod:`~sage.geometry.polyhedron.backend_ppl`) with `\QQ`
--        coefficients.
-+        (:mod:`~sage.geometry.polyhedron.backend_ppl`) with `\QQ` or
-+        `\ZZ` coefficients depending on ``base_ring``.
-
-     Some backends support further optional arguments:
-
-@@ -272,15 +272,19 @@
-         ambient_dim = 0
-
-     if backend is not None:
--        if backend=='ppl':
-+        if backend=='ppl' and base_ring is QQ:
-             from backend_ppl import Polyhedron_QQ_ppl
-             return Polyhedron_QQ_ppl(ambient_dim, Vrep, Hrep, minimize=minimize)
-+        if backend=='ppl' and base_ring is ZZ:
-+            from backend_ppl import Polyhedron_ZZ_ppl
-+            return Polyhedron_ZZ_ppl(ambient_dim, Vrep, Hrep, minimize=minimize)
-         if backend=='cddr':
-             from backend_cdd import Polyhedron_QQ_cdd
-             return Polyhedron_QQ_cdd(ambient_dim, Vrep, Hrep, verbose=verbose)
-         if backend=='cddf':
-             from backend_cdd import Polyhedron_RDF_cdd
-             return Polyhedron_RDF_cdd(ambient_dim, Vrep, Hrep, verbose=verbose)
-+        raise ValueError('No suitable backend implemented.')
-
-     if base_ring is QQ:
-         from backend_ppl import Polyhedron_QQ_ppl
-@@ -288,6 +292,9 @@
-     elif base_ring is RDF:
-         from backend_cdd import Polyhedron_RDF_cdd
-         return Polyhedron_RDF_cdd(ambient_dim, Vrep, Hrep, verbose=verbose)
-+    elif base_ring is ZZ:
-+        from backend_ppl import Polyhedron_ZZ_ppl
-+        return Polyhedron_ZZ_ppl(ambient_dim, Vrep, Hrep, minimize=minimize)
-     else:
-         raise ValueError('Polyhedron objects can only be constructed over QQ and RDF')
-
-diff --git a/sage/geometry/polyhedron/representation.py b/sage/geometry/polyhedron/representation.py
---- a/sage/geometry/polyhedron/representation.py
-+++ b/sage/geometry/polyhedron/representation.py
-@@ -60,7 +60,8 @@
-             (1, 2, 3)
-             sage: TestSuite(pr).run(skip='_test_pickling')
-         """
--        self._representation_data = tuple(data)
-+        R = polyhedron.base_ring()
-+        self._representation_data = tuple(R(x) for x in data)
-         self._polyhedron = polyhedron
-
-     def __len__(self):

File trac_12091_constraints_parents.patch

 # HG changeset patch
-# Parent 9ec5f8100986ada544f324fb383d0a3024168e12
+# Parent 11be0924d40f1d23ddc48ed1b8e72dbaef1bcc25
 
 Implement parents for constraints, fix chained inequalities
 
      def __call__(self, x):
          """
          Construct a new linear function
-@@ -1141,7 +1169,7 @@
+@@ -695,10 +723,24 @@
+             Variables:
+               x_0 is a continuous variable (min=0.0, max=+oo)
+               x_1 is a continuous variable (min=0.0, max=+oo)
++
++        With `\QQ` coefficients::
++
++            sage: p = MixedIntegerLinearProgram(solver= 'ppl')
++            sage: x = p.new_variable()
++            sage: p.set_objective(x[1] + 1/2*x[2])
++            sage: p.add_constraint(-3/5*x[1] + 2/7*x[2], max=2/5)
++            sage: p.show()
++            Maximization:
++              x_0 + 1/2 x_1
++            Constraints:
++              constraint_0: -3/5 x_0 + 2/7 x_1 <= 2/5
++            Variables:
++              x_0 is a continuous variable (min=0, max=+oo)
++              x_1 is a continuous variable (min=0, max=+oo)
+         """
+ 
+         cdef int i, j
+-        cdef double c
+         cdef GenericBackend b = self._backend
+ 
+         # inv_variables associates a MIPVariable object to an id
+@@ -1141,7 +1183,7 @@
              sage: p.add_constraint(True)
              Traceback (most recent call last):
              ...
          """
          if linear_function is 0:
              return
-@@ -1152,7 +1180,7 @@
+@@ -1152,7 +1194,7 @@
              or (max is not None and max not in RR)):
              raise ValueError("min and max arguments are required to be numerical")
  
              f = linear_function.dict()
              constant_coefficient = f.get(-1,0)
  
-@@ -1188,21 +1216,14 @@
+@@ -1188,21 +1230,14 @@
  
              self._backend.add_linear_constraint(C, min, max, name)
  
  
      def remove_constraint(self, int i):
          r"""
-@@ -1765,13 +1786,13 @@
+@@ -1765,13 +1800,13 @@
      cpdef sum(self, L):
          r"""
          Efficiently computes the sum of a sequence of
          
          .. NOTE::
          
-@@ -1793,7 +1814,7 @@
+@@ -1793,7 +1828,7 @@
          """
          d = {}
          for v in L:
                  d[id] = coeff + d.get(id,0)
          return self.linear_functions_parent()(d)
  
-@@ -2029,621 +2050,6 @@
+@@ -2029,621 +2064,6 @@
  
  
  

File trac_12339_fpgroups_libgap.patch

+# HG changeset patch
+# User Miguel Marco <mmarco@unizar.es>
+# Date 1352225182 -3600
+# Node ID b1231181ceff932c689241f04a62fc2ff2bb3328
+# Parent 927781bc4fb08f838651bba7c89c3eb0053ce084
+Ticket 12339 with libgap
+
+diff --git a/doc/en/reference/groups.rst b/doc/en/reference/groups.rst
+--- a/doc/en/reference/groups.rst
++++ b/doc/en/reference/groups.rst
+@@ -8,6 +8,8 @@
+ 
+    sage/groups/group
+    sage/groups/generic
++   sage/groups/finitely_presented
++   sage/groups/braid
+    sage/groups/abelian_gps/abelian_group
+    sage/groups/abelian_gps/values
+    sage/groups/abelian_gps/dual_abelian_group
+diff --git a/sage/groups/all.py b/sage/groups/all.py
+--- a/sage/groups/all.py
++++ b/sage/groups/all.py
+@@ -12,3 +12,8 @@
+ from class_function import ClassFunction
+ 
+ from additive_abelian.all import *
++
++from sage.misc.lazy_import import lazy_import
++
++lazy_import('sage.groups.finitely_presented', '*')
++lazy_import('sage.groups.braid', '*')
+\ No newline at end of file
+diff --git a/sage/groups/braid.py b/sage/groups/braid.py
+new file mode 100644
+--- /dev/null
++++ b/sage/groups/braid.py
+@@ -0,0 +1,827 @@
++"""
++Braid groups.
++
++AUTHOR:
++
++- Miguel Angel Marco Buzunariz
++
++Braid groups are implemented as a particular case of finitely presented groups,
++but with a lot of specific methods for braids.
++
++A braid group can be created by giving the number of strands, and the name of the generators:
++
++EXAMPLES::
++
++    sage: BraidGroup(3)
++    Braid group on 3 strands
++    sage: BraidGroup(3,'a')
++    Braid group on 3 strands
++    sage: BraidGroup(3,'a').gens()
++    (a0, a1)
++    sage: BraidGroup(3,'a,b').gens()
++    (a, b)
++
++
++The elements can be created by operating with the generators, or by passing a list
++with the indices of the letters to the group:
++
++EXAMPLES::
++
++    sage: B=BraidGroup(4)
++    sage: B.inject_variables()
++    Defining s0, s1, s2
++    sage: s0*s1*s0
++    s0*s1*s0
++    sage: B([1,2,1])
++    s0*s1*s0
++
++The mapping class action of the braid group over the free group is also implemented.
++
++EXAMPLES::
++
++    sage: B=BraidGroup(4)
++    sage: B.inject_variables()
++    Defining s0, s1, s2
++    sage: F=FreeGroup(4)
++    sage: F.inject_variables()
++    Defining x0, x1, x2, x3
++    sage: A=MappingClassGroupAction(B, F)
++    sage: A
++    Right action by Braid group on 4 strands on Free Group on generators ('x0', 'x1', 'x2', 'x3')
++    sage: A(x0, s1)
++    x0
++    sage: A(x1, s1)
++    x1*x2*x1^-1
++    sage: A(x1^-1, s1)
++    x1*x2^-1*x1^-1
++"""
++
++##############################################################################
++#       Copyright (C) 2012 Miguel Angel Marco Buzunariz <mmarco@unizar.es>
++#
++#  Distributed under the terms of the GNU General Public License (GPL)
++#
++#  The full text of the GPL is available at:
++#
++#                  http://www.gnu.org/licenses/
++##############################################################################
++
++
++
++
++from sage.groups import group
++from sage.structure.element import Element, MultiplicativeGroupElement
++from sage.categories.basic import Groups
++from sage.structure.unique_representation import UniqueRepresentation
++from sage.structure.parent_gens import ParentWithGens
++from sage.interfaces.gap import gap
++from sage.rings.integer import Integer
++from sage.rings.integer_ring import IntegerRing
++from sage.rings.polynomial.laurent_polynomial_ring import LaurentPolynomialRing
++from sage.matrix.constructor import identity_matrix, matrix
++from sage.combinat.permutation import Permutation
++from sage.categories.action import Action
++from sage.plot.bezier_path import bezier_path
++from sage.plot.plot import Graphics, line
++from sage.sets.set import Set
++from sage.rings.fraction_field import FractionField
++from sage.rings.polynomial.polynomial_ring_constructor import PolynomialRing
++from sage.plot.plot3d.shapes2 import bezier3d
++from sage.rings.infinity import Infinity
++from sage.structure.parent import normalize_names
++from sage.groups.perm_gps.permgroup import PermutationGroup
++from sage.groups.perm_gps.permgroup_element import PermutationGroupElement
++from sage.groups.finitely_presented import *
++from sage.misc.cachefunc import cached_method
++import re
++import operator
++
++
++class Braid(FinitelyPresentedGroupElement):
++    """
++    A class that models elements of the braid group. It is a particular case of element of a finitely
++    presented group.
++
++    EXAMPLES::
++
++        sage: B=BraidGroup(4)
++        sage: B
++        Braid group on 4 strands
++        sage: B.inject_variables()
++        Defining s0, s1, s2
++        sage: s0*s1/s2/s1
++        s0*s1*s2^-1*s1^-1
++        sage: B((1, 2, -3, -2))
++        s0*s1*s2^-1*s1^-1
++    """
++
++    def __cmp__(self, other):
++        """
++        TESTS::
++
++            sage: B=BraidGroup(4)
++            sage: b=B([1, 2, 1])
++            sage: c=B([2, 1, 2])
++            sage: b==c #indirect doctest
++            True
++            sage: b.__cmp__(c^(-1))
++            -1
++            sage: B([]).__cmp__(B.one())
++            0
++        """
++        if self.TietzeList()==other.TietzeList():
++            return 0
++        nfself = map(lambda i: i.TietzeList(), self.left_normal_form())
++        nfother = map(lambda i: i.TietzeList(), other.left_normal_form())
++        return cmp(nfself, nfother)
++        
++    def _latex_(self):
++        """
++        TESTS::
++
++            sage: B=BraidGroup(4)
++            sage: b=B([1, 2, 3, -1, 2, -3])
++            sage: b._latex_()
++            '\\sigma_{1}\\sigma_{2}\\sigma_{3}\\sigma_{1}^{-1}\\sigma_{2}\\sigma_{3}^{-1}'
++        """
++        latexrepr=''
++        for i in self.TietzeList():
++            if i>0:
++                latexrepr=latexrepr+"\sigma_{%s}"%i
++            if i<0:
++                latexrepr=latexrepr+"\sigma_{%s}^{-1}"%(-i)
++        return latexrepr
++
++    def strands(self):
++        """
++        returns the number of strands in the braid.
++
++        EXAMPLES::
++
++            sage: B=BraidGroup(4)
++            sage: b=B([1, 2, -1, 3, -2])
++            sage: b.strands()
++            4
++        """
++        return self.parent().strands()
++
++    def burau_matrix(self, var='t'):
++        """
++        Returns the Burau matrix of the braid.
++
++        INPUT:
++
++        - var (default='t'): the name of the variable in the entries of the matrix.
++
++        OUTPUT: The Burau matrix of the braid. It is a matrix whose entries are Laurent polynomials in the variable var.
++        
++        EXAMPLES::
++
++            sage: B=BraidGroup(4)
++            sage: B.inject_variables()
++            Defining s0, s1, s2
++            sage: b=s0*s1/s2/s1
++            sage: b.burau_matrix()
++            [     -t + 1           0    -t^2 + t         t^2]
++            [          1           0           0           0]
++            [          0           0           1           0]
++            [          0        t^-2 t^-1 - t^-2    1 - t^-1]
++            sage: s2.burau_matrix('x')
++            [     1      0      0      0]
++            [     0      1      0      0]
++            [     0      0 -x + 1      x]
++            [     0      0      1      0]
++
++        REFERENCES:
++
++            http://en.wikipedia.org/wiki/Burau_representation
++        """
++        R=LaurentPolynomialRing(IntegerRing(), var)
++        t=R.gen()
++        M=identity_matrix(R, self.strands())
++        for i in self.TietzeList():
++            A=identity_matrix(R, self.strands())
++            if i>0:
++                A[i-1, i-1]=1-t
++                A[i, i]=0
++                A[i, i-1]=1
++                A[i-1, i]=t
++            if i<0:
++                A[-1-i, -1-i]=0
++                A[-i, -i]=1-t**(-1)
++                A[-1-i, -i]=1
++                A[-i, -1-i]=t**(-1)
++            M=M*A
++        return M
++
++    def permutation(self):
++        """
++        Returns the permutation induced by the braid in its strands.
++
++        EXAMPLES::
++
++            sage: B=BraidGroup(4)
++            sage: B.inject_variables()
++            Defining s0, s1, s2
++            sage: b=s0*s1/s2/s1
++            sage: b.permutation()
++            [4, 1, 3, 2]
++        """
++        per=Permutation((()))
++        for i in self.TietzeList():
++            j=abs(i)
++            per=per*Permutation(((j, j+1)))
++        return per
++
++    def plot(self, color='blue', orientation='bottom-top', gap=0.05, aspect_ratio=1, axes=False, **kwds):
++        """
++        Plots the braid
++
++        The following options are available:
++
++         -``orientation`` - (default: 'bottom-top') determines how the braid is printed. The possible
++         values are:
++
++          -'bottom-top', the braid is printed from bottom to top
++
++          -'top-bottom', the braid is printed from top to bottom
++
++          -'left-right', the braid is printed from left to right
++
++         -``gap`` - (default: 0.05) determines the size of the gap left when a strand goes under another.
++
++        EXAMPLES::
++
++            sage: B=BraidGroup(4, 's')
++            sage: b=B([1, 2, 3, 1, 2, 1])
++            sage: b.plot()
++
++        """
++        if orientation=='top-bottom':
++            orx=0
++            ory=-1
++            nx=1
++            ny=0
++        elif orientation=='left-right':
++            orx=1
++            ory=0
++            nx=0
++            ny=-1
++        elif orientation=='bottom-top':
++            orx=0
++            ory=1
++            nx=1
++            ny=0
++        col=color
++        br=self.TietzeList()
++        n=self.strands()
++        a=Graphics()
++        op=gap
++        for i in range(len(br)):
++            m=br[i]
++            for j in range(n):
++                if m==j+1:
++                    a+=bezier_path([[(j*nx+i*orx, i*ory+j*ny), (j*nx+orx*(i+0.25), j*ny+ory*(i+0.25)), (nx*(j+0.5)+orx*(i+0.5), ny*(j+0.5)+ory*(i+0.5))], [(nx*(j+1)+orx*(i+0.75), ny*(j+1)+ory*(i+0.75)), (nx*(j+1)+orx*(i+1), ny*(j+1)+ory*(i+1))]], color=col, **kwds)
++                elif m==j:
++                    a+=bezier_path([[(nx*j+orx*i, ny*j+ory*i), (nx*j+orx*(i+0.25), ny*j+ory*(i+0.25)), (nx*(j-0.5+4*op)+orx*(i+0.5-2*op), ny*(j-0.5+4*op)+ory*(i+0.5-2*op)), (nx*(j-0.5+2*op)+orx*(i+0.5-op), ny*(j-0.5+2*op)+ory*(i+0.5-op))]], color=col, **kwds)
++                    a+=bezier_path([[(nx*(j-0.5-2*op)+orx*(i+0.5+op), ny*(j-0.5-2*op)+ory*(i+0.5+op)), (nx*(j-0.5-4*op)+orx*(i+0.5+2*op), ny*(j-0.5-4*op)+ory*(i+0.5+2*op)), (nx*(j-1)+orx*(i+0.75), ny*(j-1)+ory*(i+0.75)), (nx*(j-1)+orx*(i+1), ny*(j-1)+ory*(i+1))]], color=col, **kwds)
++                elif -m==j+1:
++                    a+=bezier_path([[(nx*j+orx*i, ny*j+ory*i), (nx*j+orx*(i+0.25), ny*j+ory*(i+0.25)), (nx*(j+0.5-4*op)+orx*(i+0.5-2*op), ny*(j+0.5-4*op)+ory*(i+0.5-2*op)), (nx*(j+0.5-2*op)+orx*(i+0.5-op), ny*(j+0.5-2*op)+ory*(i+0.5-op))]], color=col, **kwds)
++                    a+=bezier_path([[(nx*(j+0.5+2*op)+orx*(i+0.5+op), ny*(j+0.5+2*op)+ory*(i+0.5+op)), (nx*(j+0.5+4*op)+orx*(i+0.5+2*op), ny*(j+0.5+4*op)+ory*(i+0.5+2*op)), (nx*(j+1)+orx*(i+0.75), ny*(j+1)+ory*(i+0.75)), (nx*(j+1)+orx*(i+1), ny*(j+1)+ory*(i+1))]], color=col, **kwds)
++                elif -m==j:
++                    a+=bezier_path([[(nx*j+orx*i, ny*j+ory*i), (nx*j+orx*(i+0.25), ny*j+ory*(i+0.25)), (nx*(j-0.5)+orx*(i+0.5), ny*(j-0.5)+ory*(i+0.5))], [(nx*(j-1)+orx*(i+0.75), ny*(j-1)+ory*(i+0.75)), (nx*(j-1)+orx*(i+1), ny*(j-1)+ory*(i+1))]], color=col, **kwds)
++                else:
++                    a+=line([(nx*j+orx*i, ny*j+ory*i), (nx*j+orx*(i+1), ny*j+ory*(i+1))], color=col, **kwds)
++        a.set_aspect_ratio(aspect_ratio)
++        a.axes(axes)
++        return a
++
++    def plot3d(self):
++        """
++        Plots the braid in 3d.
++
++        EXAMPLES::
++
++            sage: B=BraidGroup(4, 's')
++            sage: b=B([1, 2, 3, 1, 2, 1])
++            sage: b.plot3d()
++
++        """
++        b=[]
++        braid=self.TietzeList()
++        n=self.strands()
++        for i in range(len(braid)):
++            m=braid[i]
++            for j in range(n):
++                if m==j+1:
++                    b.append(bezier3d([[(0, j, i), (0, j, i+0.25), (0.25, j, i+0.25), (0.25, j+0.5, i+0.5)], [(0.25, j+1, i+0.75), (0, j+1, i+0.75), (0, j+1, i+1)]]))
++                elif -m==j+1:
++                    b.append(bezier3d([[(0, j, i), (0, j, i+0.25), (-0.25, j, i+0.25), (-0.25, j+0.5, i+0.5)], [(-0.25, j+1, i+0.75), (0, j+1, i+0.75), (0, j+1, i+1)]]))
++                elif m==j:
++                    b.append(bezier3d([[(0, j, i), (0, j, i+0.25), (-0.25, j, i+0.25), (-0.25, j-0.5, i+0.5)], [(-0.25, j-1, i+0.75), (0, j-1, i+0.75), (0, j-1, i+1)]]))
++                elif -m==j:
++                    b.append(bezier3d([[(0, j, i), (0, j, i+0.25), (0.25, j, i+0.25), (0.25, j-0.5, i+0.5)], [(0.25, j-1, i+0.75), (0, j-1, i+0.75), (0, j-1, i+1)]]))
++                else:
++                    b.append(bezier3d([[(0, j, i), (0, j, i+1)]]))
++        return sum(b)
++
++    @cached_method
++    def LKB_matrix(self, variables='x,y'):
++        """
++        The matrix corresponding to the Lawence-Krammer-Bigelow representation of the braid.
++        The matrix is expressed in the basis $\{e_{i, j} \mid 1\\leq i < j \leq n\}$, where
++        the indices are ordered lexicographically.
++        It is a matrix whose entries are in the ring of Laurent polynomials on the given variables.
++        By default, the variables are 'x' and 'y'.
++
++        INPUT:
++
++        -variables (default='x,y'): a string containing the names of the variables, separated by a comma.
++
++        OUTPUT: The matrix corresponding to the Lawence-Krammer-Bigelow representation of the braid.
++        
++        EXAMPLES::
++
++            sage: B=BraidGroup(3)
++            sage: b=B([1, 2, 1])
++            sage: b.LKB_matrix()
++            [             0 -x^4*y + x^3*y         -x^4*y]
++            [             0         -x^3*y              0]
++            [        -x^2*y  x^3*y - x^2*y              0]
++            sage: c=B([2, 1, 2])
++            sage: c.LKB_matrix()
++            [             0 -x^4*y + x^3*y         -x^4*y]
++            [             0         -x^3*y              0]
++            [        -x^2*y  x^3*y - x^2*y              0]
++
++        REFERENCES:
++
++        .. [Bigelow] Bigelow, Stephen J. The Lawrence-Krammer representation. arXiv:math/0204057v1
++
++        """
++        return self.parent()._LKB_matrix_(tuple(self.TietzeList()), variab=variables)
++
++    @cached_method
++    def left_normal_form(self):
++        """
++        Returns the left normal form of the braid.
++
++        The output is a list of the elements of the left normal form. The first element is a
++        power of $\Delta$, and the rest are permutation braids.
++
++        EXAMPLES::
++
++
++            sage: B=BraidGroup(4)
++            sage: b=B([1, 2, 3, -1, 2, -3])
++            sage: b.left_normal_form()
++            [s0^-1*s1^-1*s2^-1*s0^-1*s1^-1*s0^-1, s0*s1*s2*s1*s0, s0*s2*s1]
++            sage: c=B([1])
++            sage: c.left_normal_form()
++            [<identity ...>, s0]
++        """
++        lnfp=self._left_normal_form_perm_()
++        a=lnfp[0]
++        l=lnfp[1:]
++        n=self.strands()
++        delta=Permutation([n-i for i in range(n)])
++        return [self.parent()._permutation_braid(delta).__pow__(a)]+map(lambda i:self.parent()._permutation_braid(i), l)
++        
++    @cached_method
++    def _left_normal_form_perm_(self):
++        """
++        Returns the left normal form of the braid, in permutation form.
++
++        The output is a list whose first element is the power of $\Delta$, and the rest are the permutations corresponding to the simple factors.
++
++        EXAMPLES::
++
++            sage: B=BraidGroup(12)
++            sage: B([2, 2, 2, 3, 1, 2, 3, 2, 1, -2])._left_normal_form_perm_()
++            [-1, [12, 11, 10, 9, 8, 7, 6, 5, 2, 4, 3, 1], [4, 1, 3, 2, 5, 6, 7, 8, 9, 10, 11, 12], [2, 3, 1, 4, 5, 6, 7, 8, 9, 10, 11, 12], [3, 1, 2, 4, 5, 6, 7, 8, 9, 10, 11, 12], [2, 3, 1, 4, 5, 6, 7, 8, 9, 10, 11, 12]]
++            sage: C=BraidGroup(6)
++            sage: C([2, 3, -4, 2, 3, -5, 1, -2, 3, 4, 1, -2])._left_normal_form_perm_()
++            [-2, [3, 5, 4, 2, 6, 1], [1, 6, 3, 5, 2, 4], [5, 6, 2, 4, 1, 3], [3, 2, 4, 1, 5, 6], [1, 5, 2, 3, 4, 6]]
++        """
++        n=self.parent().strands()
++        delta=0
++        Delta=Permutation([n-i for i in range(n)])
++        l=list(self.TietzeList())
++        if l==[]:
++            return [0]
++        form=[]
++        for i in l:
++            if i>0:
++                form.append(Permutation((i, i+1)))
++            else:
++                delta=delta+1
++                form=map(lambda a: Delta*a*Delta, form)
++                form.append(Delta*Permutation((-i, -i+1)))
++        i=0
++        j=0
++        while j<len(form):
++            while i<len(form)-j-1:
++                e=form[i].inverse().descents()
++                s=form[i+1].descents()
++                S=set(s).difference(set(e))
++                while S!=set([]):
++                    a=list(S)[0]
++                    form[i]=form[i]*Permutation((a+1, a+2))
++                    form[i+1]=Permutation((a+1, a+2))*form[i+1]
++                    e=form[i].inverse().descents()
++                    s=form[i+1].descents()
++                    S=set(s).difference(set(e))
++                if form[i+1].length()==0:
++                    form.pop(i+1)
++                    i=0
++                else:
++                    i=i+1
++            j=j+1
++            i=0
++        form=filter(lambda a: a.length()>0, form)
++        while form!=[] and form[0]==Delta:
++            form.pop(0)
++            delta=delta-1
++        return [-delta]+form
++
++
++class BraidGroup(FinitelyPresentedGroup):
++    """
++    The braid group on n strands.
++
++    EXAMPLES::
++
++        sage: B1=BraidGroup(5)
++        sage: B1
++        Braid group on 5 strands
++        sage: B2=BraidGroup(3)
++        sage: B1==B2
++        False
++        sage: B2 is BraidGroup(3)
++        True
++    """
++    Element=Braid
++
++    def __init__(self, n, names='s'):
++        """
++        TESTS::
++
++
++            sage: B1=BraidGroup(5) # indirect doctest
++            sage: B1
++            Braid group on 5 strands
++        """
++        if not n in IntegerRing() or n<2:
++            raise ValueError, "n must be an integer bigger than one"
++        self._freegroup_=FreeGroup(n-1, names)
++        self._names_=names
++        rels=[]
++        for i in range(1, n):
++            if i<n-1:
++                rels.append(self._freegroup_([i, i+1, i, -i-1, -i, -i-1]))
++            for j in range(i+2, n):
++                rels.append(self._freegroup_([i, j, -i, -j]))
++        self._rels_=tuple(rels)
++        lis=libgap([i.gap() for i in rels])
++        self._gap_repr_=self._freegroup_.gap()/lis
++        #group.Group.__init__(self)
++        #self._assign_names(self._freegroup_._gens_str_)
++        Parent.__init__(self,gens=self._freegroup_._gens_str_,category=Groups())
++        self._nstrands_=n
++
++    def __reduce__(self):
++        """
++        TESTS::
++
++            sage: B=BraidGroup(3)
++            sage: B.__reduce__()
++            (<class 'sage.groups.braid.BraidGroup'>, (3,))
++            sage: B=BraidGroup(3, 'sigma')
++            sage: B.__reduce__()
++            (<class 'sage.groups.braid.BraidGroup'>, (3, 'sigma'))
++
++        """
++        if self._names_=='s':
++            return (BraidGroup, (self._nstrands_, ))
++        return (BraidGroup, (self._nstrands_, self._names_))
++
++    def _repr_(self):
++        """
++        TESTS::
++
++            sage: B1=BraidGroup(5)
++            sage: B1 # indirect doctest
++            Braid group on 5 strands
++        """
++        return "Braid group on %s strands"%self._nstrands_
++
++    def size(self):
++        """
++        TESTS::
++
++            sage: B1=BraidGroup(5)
++            sage: B1.size()
++            +Infinity
++        """
++        return Infinity
++    cardinality=size
++    order=size
++    
++    def permutation_group(self):
++        """
++        Returns an error, since braid groups are infinite.
++        
++        TESTS::
++
++            sage: B=BraidGroup(4, 'g')
++            sage: try:
++            ...     B.permutation_group()
++            ... except ValueError as exc:
++            ...     print exc
++            The group is infinite
++        """
++        raise ValueError, "The group is infinite"
++
++    def strands(self):
++        """
++        Returns the number of strands of the braid group
++
++        EXAMPLES::
++
++            sage: B=BraidGroup(4)
++            sage: B.strands()
++            4
++        """
++        return self._nstrands_
++
++    def _element_constructor_(self, x):
++        """
++        TESTS::
++
++            sage: B=BraidGroup(4)
++            sage: B([1, 2, 3]) # indirect doctest
++            s0*s1*s2
++        """
++        return Braid(x, parent=self)
++
++    @cached_method
++    def _permutation_braid_list(self, p):
++        """
++        Constructs the braid that corresponds to the given permutation. It is the only braid with
++        the following properties:
++
++         - The braid induces the given permutation.
++
++         - The braid is positive (that is, it can be writen without using the inverses of the generators).
++
++         - Every two strands cross each other at most once.
++
++        INPUT:
++
++        -p: a permutation
++
++        Output: the lexicographically smallest word that represents the braid, in Tietze list form.
++
++        EXAMPLES::
++
++            sage: B=BraidGroup(5)
++            sage: P=Permutation([5, 3, 1, 2, 4])
++            sage: B._permutation_braid_list(P)
++            [1, 2, 1, 3, 2, 4]
++
++        """
++        if p.length()==0:
++            return []
++        pl=p
++        l=[]
++        while pl.length()>0:
++            i=1
++            while i<max(pl):
++                if pl(i)>pl(i+1):
++                    l.append(i)
++                    pl=Permutation([(i, i+1)])*pl
++                    i=1
++                else:
++                    i=i+1
++        return l
++
++    @cached_method
++    def _permutation_braid(self, p):
++        """
++        Constructs the braid that corresponds to the given permutation. It is the only braid with
++        the following properties:
++
++         - The braid induces the given permutation.
++
++         - The braid is positive (that is, it can be writen without using the inverses of the generators).
++
++         - Every two strands cross each other at most once.
++
++        INPUT:
++
++        -p: a permutation.
++
++        OUTPUT: The braid that corresponds to the permutation.
++
++        EXAMPLES::
++
++            sage: B=BraidGroup(5)
++            sage: P=Permutation([5, 3, 1, 2, 4])
++            sage: B._permutation_braid(P)
++            s0*s1*s0*s2*s1*s3
++
++        """
++        return self(self._permutation_braid_list(p))
++
++    @cached_method
++    def _LKB_matrix_(self, braid, variab):
++        """
++        Returns the matrix corresponding to the Lawrence-Krammer-Bigelow representation of the braid given by the tuple.
++        The variables of the matrix must be given.
++        This function is included here to improve the time gained by the caching.
++
++        INPUT:
++
++            -braid: a tuple whose entries are the entries of the Tietze list of the braid.
++
++            -variab: the names of the variables that will appear in the matrix. They must be given as a string, separated by a comma
++            
++        OUTPUT: The LKB matrix of the braid, with respect to the variables.
++
++        TESTS::
++
++            sage: B=BraidGroup(3)
++            sage: B._LKB_matrix_((2, 1, 2), 'x, y')
++            [             0 -x^4*y + x^3*y         -x^4*y]
++            [             0         -x^3*y              0]
++            [        -x^2*y  x^3*y - x^2*y              0]
++            sage: B._LKB_matrix_((1, 2, 1), 'x, y')
++            [             0 -x^4*y + x^3*y         -x^4*y]
++            [             0         -x^3*y              0]
++            [        -x^2*y  x^3*y - x^2*y              0]
++            sage: B._LKB_matrix_((-1, -2, -1, 2, 1, 2), 'x, y')
++            [1 0 0]
++            [0 1 0]
++            [0 0 1]
++
++        """
++        n=self.strands()
++        if len(braid)>1:
++            A=self._LKB_matrix_(braid[:1], variab)
++            for i in braid[1:]:
++                A=A*self._LKB_matrix_((i, ), variab)
++            return A
++        l=list(Set(range(n)).subsets(2))
++        R=LaurentPolynomialRing(IntegerRing(), variab)
++        q=R.gens()[0]
++        t=R.gens()[1]
++        if len(braid)==0:
++            return identity_matrix(R, len(l), sparse=True)
++        A=matrix(R, len(l), sparse=True)
++        if braid[0]>0:
++            i=braid[0]-1
++            for m in range(len(l)):
++                j=min(l[m])
++                k=max(l[m])
++                if i==j-1:
++                    A[l.index(Set([i, k])), m]=q
++                    A[l.index(Set([i, j])), m]=q*q-q
++                    A[l.index(Set([j, k])), m]=1-q
++                elif i==j and not j==k-1:
++                    A[l.index(Set([j, k])), m]=0
++                    A[l.index(Set([j+1, k])), m]=1
++                elif k-1==i and not k-1==j:
++                    A[l.index(Set([j, i])), m]=q
++                    A[l.index(Set([j, k])), m]=1-q
++                    A[l.index(Set([i, k])), m]=(1-q)*q*t
++                elif i==k:
++                    A[l.index(Set([j, k])), m]=0
++                    A[l.index(Set([j, k+1])), m]=1
++                elif i==j and j==k-1:
++                    A[l.index(Set([j, k])), m]=-t*q*q
++                else:
++                    A[l.index(Set([j, k])), m]=1
++            return A
++        else:
++            i=-braid[0]-1
++            for m in range(len(l)):
++                j=min(l[m])
++                k=max(l[m])
++                if i==j-1:
++                    A[l.index(Set([j-1, k])), m]=1
++                elif i==j and not j==k-1:
++                    A[l.index(Set([j+1, k])), m]=q**(-1)
++                    A[l.index(Set([j, k])), m]=1-q**(-1)
++                    A[l.index(Set([j, j+1])), m]=t**(-1)*q**(-1)-t**(-1)*q**(-2)
++                elif k-1==i and not k-1==j:
++                    A[l.index(Set([j, k-1])), m]=1
++                elif i==k:
++                    A[l.index(Set([j, k+1])), m]=q**(-1)
++                    A[l.index(Set([j, k])), m]=1-q**(-1)
++                    A[l.index(Set([k, k+1])), m]=-q**(-1)+q**(-2)
++                elif i==j and j==k-1:
++                    A[l.index(Set([j, k])), m]=-t**(-1)*q**(-2)
++                else:
++                    A[l.index(Set([j, k])), m]=1
++            return A
++            #M=self._LKB_matrix_((-braid[0], ), variab).inverse()
++            #ML=M.list()
++            #MIR=FractionField(PolynomialRing(IntegerRing(), variab))
++            #ML=[R(MIR(i).numerator())*R(MIR(i).denominator())**(-1) for i in ML]
++            #M=matrix(len(l), len(l), ML)
++            #return M
++
++
++class MappingClassGroupAction(Action):
++    r"""
++    The action of the braid group the free group as the mapping class group of the punctured disk.
++    This action goes as follows:
++
++    .. MATH::
++    
++        x_j \cdot \sigma_i=\begin{cases}
++        x_{j}\cdot x_{j+1}\cdot {x_j}^{-1} & \text{if $i=j$} \\
++        x_{j-1} & \text{if $i=j-1$} \\
++        x_{j} & \text{otherwise}
++        \end{cases}
++
++    Where $\sigma_i$ are the generators of the braid group on $n$ strands, and $x_j$ the generators
++    of the free group of rank $n$.
++
++
++    EXAMPLES::
++    
++        sage: B=BraidGroup(4)
++        sage: B.inject_variables()
++        Defining s0, s1, s2
++        sage: F=FreeGroup(4)
++        sage: F.inject_variables()
++        Defining x0, x1, x2, x3
++        sage: A=MappingClassGroupAction(B, F)
++        sage: A
++        Right action by Braid group on 4 strands on Free Group on generators ('x0', 'x1', 'x2', 'x3')
++        sage: A(x0, s1)
++        x0
++        sage: A(x1, s1)
++        x1*x2*x1^-1
++        sage: A(x1^-1, s1)
++        x1*x2^-1*x1^-1
++
++    It's also possible to register the action to allow multiplication of free group elements by braids::
++
++        sage: F._unset_coercions_used()
++        sage: F.register_action(A)
++        sage: x2*s2
++        x2*x3*x2^-1
++        sage: x2*s1^(-1)
++        x2^-1*x1*x2
++
++        """
++        
++    def __init__(self, G, M, is_left=0):
++        """
++        TESTS::
++
++            sage: B=BraidGroup(3)
++            sage: G=FreeGroup('a, b, c')
++            sage: MappingClassGroupAction(B, G) # indirect doctest
++            Right action by Braid group on 3 strands on Free Group on generators ('a', 'b', 'c')
++        """
++        Action.__init__(self, G, M, is_left, operator.mul)
++    
++    def _call_(self, x, b):
++        """
++        TESTS::
++
++            sage: B=BraidGroup(3)
++            sage: G=FreeGroup('a, b, c')
++            sage: A=MappingClassGroupAction(B, G)
++            sage: A(G.0, B.0) # indirect doctest
++            a*b*a^-1
++            sage: A(G.1, B.0) # indirect doctest
++            a
++        """
++        t=list(x.TietzeList())
++        for j in b.TietzeList():
++            s=[]
++            for i in t:
++                if j==i and i>0:
++                    s+=[i, i+1, -i]
++                elif j==-i and i<0:
++                    s+=[-i, i-1, i]
++                elif j==-i and i>0:
++                    s+=[i+1]
++                elif j==i and i<0:
++                    s+=[i-1]
++                elif i>0 and j==i-1:
++                    s+=[i-1]
++                elif i<0 and j==-i-1:
++                    s+=[i+1]
++                elif i>0 and -j==i-1:
++                    s+=[-i, i-1, i]
++                elif i<0 and j==i+1:
++                    s+=[i, i+1, -i]
++                else:
++                    s+=[i]
++            t=s
++        return self.codomain()(list(t))
+diff --git a/sage/groups/finitely_presented.py b/sage/groups/finitely_presented.py
+new file mode 100644
+--- /dev/null
++++ b/sage/groups/finitely_presented.py
+@@ -0,0 +1,1498 @@
++"""
++Free and finitely presented groups.
++
++AUTHOR:
++
++- Miguel Angel Marco Buzunariz
++
++Free groups and finitely presented groups are implemented as a wrapper
++over the corresponing GAP objects.
++
++A free group can be created by giving the number of generators, or their names.
++It is also possible to create indexed generators:
++
++EXAMPLES::
++
++    sage: FreeGroup(3)
++    Free Group on generators ('x0', 'x1', 'x2')
++    sage: FreeGroup('a,b,c')
++    Free Group on generators ('a', 'b', 'c')
++    sage: FreeGroup(3,'t')
++    Free Group on generators ('t0', 't1', 't2')
++
++The elements can be created by operating with the generators, or by passing a list
++with the indices of the letters to the group:
++
++EXAMPLES::
++
++    sage: G=FreeGroup('a,b,c')
++    sage: G.inject_variables()
++    Defining a, b, c
++    sage: a*b*c*a
++    a*b*c*a
++    sage: G([1,2,3,1])
++    a*b*c*a
++    sage: a*b/c*b^2
++    a*b*c^-1*b^2
++    sage: G([1,1,2,-1,-3,2])
++    a^2*b*a^-1*c^-1*b
++
++Finitely presented groups are constructed as quotients of free groups. The way to
++create their elements is the same as in the case of free groups.
++
++EXAMPLES::
++
++    sage: F=FreeGroup('a,b,c')
++    sage: F.inject_variables()
++    Defining a, b, c
++    sage: G=F.quotient([a^2,b^2,c^2,a*b*c*a*b*c])
++    sage: G
++    Finitely Presented Group on generators ('a', 'b', 'c')
++    and relations (a^2, b^2, c^2, a*b*c*a*b*c)
++    sage: G([1,2,-1])
++    a*b*a^-1
++    sage: a.parent()
++    Free Group on generators ('a', 'b', 'c')
++    sage: G.inject_variables()
++    Defining a, b, c
++    sage: a.parent()
++    Finitely Presented Group on generators ('a', 'b', 'c')
++    and relations (a^2, b^2, c^2, a*b*c*a*b*c)