Ticket #11395: trac_11395_update_gfan_vb.patch

File trac_11395_update_gfan_vb.patch, 26.8 KB (added by vbraun, 7 years ago)

Added commit message

  • sage/rings/polynomial/groebner_fan.py

    # HG changeset patch
    # User Marshall Hampton <hamptonio@gmail.com>
    # Date 1342132172 18000
    # Node ID d5ee5f582d327166d47d7f0f6c89cab3b6afe39e
    # Parent  cb2854556f7626167cd6523a37ae7a58f4692aef
    Update GFan to version 0.5
    
    diff --git a/sage/rings/polynomial/groebner_fan.py b/sage/rings/polynomial/groebner_fan.py
    a b  
    7676from sage.plot.all import line, Graphics, polygon
    7777from sage.plot.plot3d.shapes2 import line3d
    7878from sage.geometry.polyhedron.constructor import Polyhedron
     79from sage.geometry.fan import Fan
     80from sage.matrix.constructor import matrix
     81from sage.misc.misc_c import prod
    7982
    8083def prefix_check(str_list):
    8184    """
     
    128131    EXAMPLES::
    129132   
    130133        sage: R.<x,y,z,w> = PolynomialRing(QQ,4)
    131         sage: ts = R.ideal([x^2+y^2+z^2-1,x^4-y^2-z-1,x+y+z,w+x+y])
    132         sage: tsg = ts.groebner_fan()
    133         sage: tstr = tsg.tropical_intersection()
     134        sage: I = R.ideal([x^2+y^2+z^2-1,x^4-y^2-z-1,x+y+z,w+x+y])
     135        sage: GF = I.groebner_fan()
     136        sage: TI = GF.tropical_intersection()
    134137        sage: from sage.rings.polynomial.groebner_fan import _cone_parse
    135         sage: _cone_parse(tstr.fan_dict['CONES'])
     138        sage: _cone_parse(TI.fan_dict['CONES'])
    136139        {1: [[0], [1], [2], [3], [4]], 2: [[2, 3]]}
    137140    """
    138141    cone_dict = {}
     
    277280        return self._relative_interior_point
    278281   
    279282class PolyhedralFan(SageObject):
    280     def __init__(self, gfan_polyhedral_fan):
     283    def __init__(self, gfan_polyhedral_fan, parameter_indices = []):
    281284        """
    282285        Converts polymake/gfan data on a polyhedral fan into a sage class.
    283         Currently (18-03-2008) needs a lot of work.
    284286       
    285287        INPUT:
    286288       
     
    300302        """
    301303        fan_keys = ['AMBIENT_DIM','DIM','LINEALITY_DIM','RAYS','N_RAYS',
    302304                    'LINEALITY_SPACE','ORTH_LINEALITY_SPACE','F_VECTOR',
    303                     'CONES','MAXIMAL_CONES','PURE']
     305                    'CONES','MAXIMAL_CONES','PURE','SIMPLICIAL','MULTIPLICITIES']
    304306        poly_lines = gfan_polyhedral_fan.split('\n')
    305307        self.fan_dict = {}
    306308        key_ind = 0
     
    319321            temp_ray = ray.split('\t')[0]
    320322            temp_ray = temp_ray.split(' ')
    321323            temp_ray = [int(x) for x in temp_ray]
     324            if parameter_indices != []:
     325                for q in parameter_indices:
     326                    temp_ray = temp_ray[0:q] + [0] + temp_ray[q:]
    322327            self._rays.append(temp_ray)
    323328        self._cone_dict = _cone_parse(self.fan_dict['CONES'])
     329        self._maximal_cone_dict = _cone_parse(self.fan_dict['MAXIMAL_CONES'])
    324330        self._str = gfan_polyhedral_fan
    325331
    326332    def _repr_(self):
     
    349355            sage: gf = R3.ideal([x^8-y^4,y^4-z^2,z^2-2]).groebner_fan()
    350356            sage: pf = gf.polyhedralfan()
    351357            sage: pf._str_()
    352             '_application PolyhedralFan\n_version 2.2\n_type PolyhedralFan\n\nAMBIENT_DIM\n3\n\nDIM\n3\n\nLINEALITY_DIM\n0\n\nRAYS\n0 0 1\t# 0\n0 1 0\t# 1\n1 0 0\t# 2\n\nN_RAYS\n3\n\nLINEALITY_SPACE\n\nORTH_LINEALITY_SPACE\n1 0 0\n0 1 0\n0 0 1\n\nF_VECTOR\n1 3 3 1\n\nMY_EULER\n0\n\nSIMPLICIAL\n1\n\nPURE\n1\n\nCONES\n{}\t# Dimension 0\n{0}\t# Dimension 1\n{1}\n{2}\n{0 1}\t# Dimension 2\n{0 2}\n{1 2}\n{0 1 2}\t# Dimension 3\n\nMAXIMAL_CONES\n{0 1 2}\t# Dimension 3\n'
     358            '_application fan\n_version 2.2\n_type SymmetricFan\n\nAMBIENT_DIM\n3\n\nDIM\n3\n\nLINEALITY_DIM\n0\n\nRAYS\n0 0 1\t# 0\n0 1 0\t# 1\n1 0 0\t# 2\n\nN_RAYS\n3\n\nLINEALITY_SPACE\n\nORTH_LINEALITY_SPACE\n1 0 0\n0 1 0\n0 0 1\n\nF_VECTOR\n1 3 3 1\n\nSIMPLICIAL\n1\n\nPURE\n1\n\nCONES\n{}\t# Dimension 0\n{0}\t# Dimension 1\n{1}\n{2}\n{0 1}\t# Dimension 2\n{0 2}\n{1 2}\n{0 1 2}\t# Dimension 3\n\nMAXIMAL_CONES\n{0 1 2}\t# Dimension 3\n'
    353359        """
    354360        return self._str
    355361
     
    383389   
    384390    def lineality_dim(self):
    385391        """
    386         Returns the lineality dimension of the Groebner fan. This is
    387         just the difference between the ambient dimension and the dimension
    388         of the cone.
     392        Returns the lineality dimension of the fan. This is the
     393        dimension of the largest subspace contained in the fan.
    389394       
    390395        EXAMPLES::
    391396       
     
    399404
    400405    def rays(self):
    401406        """
    402         Returns a list of rays of the polyhedral fan.
     407        A list of rays of the polyhedral fan.
    403408       
    404409        EXAMPLES::
    405410       
     
    411416            [[-1, 0, 1], [-1, 1, 0], [1, -2, 1], [1, 1, -2], [2, -1, -1]]
    412417        """
    413418        return sorted(self._rays)
     419
     420    def cones(self):
     421        """
     422        A dictionary of cones in which the keys are the cone dimensions.
     423        For each dimension, the value is a list of the cones,
     424        where each element consists of a list of ray indices.
    414425       
     426        EXAMPLES::
     427       
     428            sage: R.<x,y,z> = QQ[]
     429            sage: f = 1+x+y+x*y
     430            sage: I = R.ideal([f+z*f, 2*f+z*f, 3*f+z^2*f])
     431            sage: GF = I.groebner_fan()
     432            sage: PF = GF.tropical_intersection()
     433            sage: PF.cones()
     434            {1: [[0], [1], [2], [3], [4], [5]], 2: [[0, 1], [0, 2], [0, 3], [0, 4], [1, 2], [1, 3], [2, 4], [3, 4], [1, 5], [2, 5], [3, 5], [4, 5]]}
     435        """
     436        return self._cone_dict
     437
     438    def maximal_cones(self):
     439        """
     440        A dictionary of the maximal cones in which the keys are the
     441        cone dimensions.  For each dimension, the value is a list of
     442        the maximal cones, where each element consists of a list of ray indices. 
     443       
     444        EXAMPLES::
     445       
     446            sage: R.<x,y,z> = QQ[]
     447            sage: f = 1+x+y+x*y
     448            sage: I = R.ideal([f+z*f, 2*f+z*f, 3*f+z^2*f])
     449            sage: GF = I.groebner_fan()
     450            sage: PF = GF.tropical_intersection()
     451            sage: PF.maximal_cones()
     452            {2: [[0, 1], [0, 2], [0, 3], [0, 4], [1, 2], [1, 3], [2, 4], [3, 4], [1, 5], [2, 5], [3, 5], [4, 5]]}
     453        """
     454        return self._maximal_cone_dict
     455
     456    def f_vector(self):
     457        """
     458        The f-vector of the fan.
     459       
     460        EXAMPLES::
     461       
     462            sage: R.<x,y,z> = QQ[]
     463            sage: f = 1+x+y+x*y
     464            sage: I = R.ideal([f+z*f, 2*f+z*f, 3*f+z^2*f])
     465            sage: GF = I.groebner_fan()
     466            sage: PF = GF.tropical_intersection()
     467            sage: PF.f_vector()
     468            [1, 6, 12]
     469        """
     470        str_data = self.fan_dict['F_VECTOR'][0]
     471        fv = [Integer(x) for x in str_data.split(' ')]
     472        return fv
     473
     474    def is_simplicial(self):
     475        """
     476        Whether the fan is simplicial or not.
     477
     478        EXAMPLES::
     479       
     480            sage: R.<x,y,z> = QQ[]
     481            sage: f = 1+x+y+x*y
     482            sage: I = R.ideal([f+z*f, 2*f+z*f, 3*f+z^2*f])
     483            sage: GF = I.groebner_fan()
     484            sage: PF = GF.tropical_intersection()
     485            sage: PF.is_simplicial()
     486            True
     487        """
     488        return bool(int(self.fan_dict['SIMPLICIAL'][0]))
     489
     490    def to_RationalPolyhedralFan(self):
     491        """
     492        Converts to the RationalPolyhedralFan class, which is more actively
     493        maintained.  While the information in each class is essentially the
     494        same, the methods and implementation are different.
     495
     496        EXAMPLES::
     497       
     498            sage: R.<x,y,z> = QQ[]
     499            sage: f = 1+x+y+x*y
     500            sage: I = R.ideal([f+z*f, 2*f+z*f, 3*f+z^2*f])
     501            sage: GF = I.groebner_fan()
     502            sage: PF = GF.tropical_intersection()
     503            sage: fan = PF.to_RationalPolyhedralFan()
     504            sage: [q.facet_normals() for q in fan]
     505            [(M(0, -1, 0), M(-1, 0, 0)), (M(0, 0, -1), M(-1, 0, 0)), (M(0, 0, 1), M(-1, 0, 0)), (M(0, 1, 0), M(-1, 0, 0)), (M(0, 0, -1), M(0, -1, 0)), (M(0, 0, 1), M(0, -1, 0)), (M(0, 1, 0), M(0, 0, -1)), (M(0, 1, 0), M(0, 0, 1)), (M(1, 0, 0), M(0, -1, 0)), (M(1, 0, 0), M(0, 0, -1)), (M(1, 0, 0), M(0, 0, 1)), (M(1, 0, 0), M(0, 1, 0))]
     506
     507        Here we use the RationalPolyhedralFan's Gale_transform method on a tropical
     508        prevariety.
     509       
     510        .. link
     511
     512        ::
     513       
     514            sage: fan.Gale_transform()
     515            [ 1  0  0  0  0  1 -2]
     516            [ 0  1  0  0  1  0 -2]
     517            [ 0  0  1  1  0  0 -2]
     518
     519        """
     520        try:
     521            return self._fan
     522        except:
     523            cdnt = []
     524            cones = self.cones()
     525            for x in cones:
     526                if x > 1:
     527                    cdnt = cdnt + cones[x]
     528            fan = Fan(cones=cdnt, rays = self.rays(), discard_faces=True)
     529            self._fan = fan
     530            return self._fan
     531
     532class InitialForm(SageObject):
     533    def __init__(self, cone, rays, initial_forms):
     534        """
     535        A system of initial forms from a polynomial system.
     536        To each form is associated a cone and a list of
     537        polynomials (the initial form system itself).
     538
     539        This class is intended for internal use inside of the
     540        TropicalPrevariety class.
     541
     542        EXAMPLES::
     543       
     544            sage: from sage.rings.polynomial.groebner_fan import InitialForm
     545            sage: R.<x,y> = QQ[]
     546            sage: inform = InitialForm([0], [[-1, 0]], [y^2 - 1, y^2 - 2, y^2 - 3])
     547            sage: inform._cone
     548            [0]
     549        """
     550        self._cone = cone
     551        self._rays = rays
     552        self._initial_forms = initial_forms
     553
     554
     555    def cone(self):
     556        """
     557        The cone associated with the initial form system.
     558       
     559        EXAMPLES::
     560       
     561            sage: R.<x,y> = QQ[]
     562            sage: I = R.ideal([(x+y)^2-1,(x+y)^2-2,(x+y)^2-3])
     563            sage: GF = I.groebner_fan()
     564            sage: PF = GF.tropical_intersection()
     565            sage: pfi0 = PF.initial_form_systems()[0]
     566            sage: pfi0.cone()
     567            [0]
     568        """
     569        return self._cone
     570
     571    def rays(self):
     572        """
     573        The rays of the cone associated with the initial form system.
     574
     575        EXAMPLES::
     576       
     577            sage: R.<x,y> = QQ[]
     578            sage: I = R.ideal([(x+y)^2-1,(x+y)^2-2,(x+y)^2-3])
     579            sage: GF = I.groebner_fan()
     580            sage: PF = GF.tropical_intersection()
     581            sage: pfi0 = PF.initial_form_systems()[0]
     582            sage: pfi0.rays()
     583            [[-1, 0]]
     584        """
     585        return self._rays
     586
     587    def internal_ray(self):
     588        """
     589        A ray internal to the cone associated with the initial form
     590        system.
     591
     592        EXAMPLES::
     593       
     594            sage: R.<x,y> = QQ[]
     595            sage: I = R.ideal([(x+y)^2-1,(x+y)^2-2,(x+y)^2-3])
     596            sage: GF = I.groebner_fan()
     597            sage: PF = GF.tropical_intersection()
     598            sage: pfi0 = PF.initial_form_systems()[0]
     599            sage: pfi0.internal_ray()
     600            (-1, 0)
     601        """
     602        return sum([vector(q) for q in self.rays()])
     603
     604    def initial_forms(self):
     605        """
     606        The initial forms (polynomials).
     607
     608        EXAMPLES::
     609       
     610            sage: R.<x,y> = QQ[]
     611            sage: I = R.ideal([(x+y)^2-1,(x+y)^2-2,(x+y)^2-3])
     612            sage: GF = I.groebner_fan()
     613            sage: PF = GF.tropical_intersection()
     614            sage: pfi0 = PF.initial_form_systems()[0]
     615            sage: pfi0.initial_forms()
     616            [y^2 - 1, y^2 - 2, y^2 - 3]
     617        """
     618        return self._initial_forms
     619
     620def verts_for_normal(normal, poly):
     621    """
     622    Returns the exponents of the vertices of a newton polytope
     623    that make up the supporting hyperplane for the given outward
     624    normal.
     625
     626    EXAMPLES::
     627
     628        sage: from sage.rings.polynomial.groebner_fan import verts_for_normal
     629        sage: R.<x,y,z> = PolynomialRing(QQ,3)
     630        sage: f1 = x*y*z - 1
     631        sage: f2 = f1*(x^2 + y^2 + 1)
     632        sage: verts_for_normal([1,1,1],f2)
     633        [(3, 1, 1), (1, 3, 1)]
     634    """
     635    exps = [tuple(x) for x in poly.exponents()]
     636    expmat = matrix(exps)
     637    vals = expmat*vector(QQ,normal)
     638    maxval = max(vals)
     639    outverts = []
     640    for i in range(len(exps)):
     641        if vals[i] == maxval:
     642            outverts.append(exps[i])
     643    return outverts
     644
     645class TropicalPrevariety(PolyhedralFan):
     646   
     647    def __init__(self, gfan_polyhedral_fan, polynomial_system, poly_ring, parameters = []):
     648        """
     649        This class is a subclass of the PolyhedralFan class,
     650        with some additional methods for tropical prevarieties.
     651       
     652        INPUT:
     653       
     654       
     655        -  ``gfan_polyhedral_fan`` - output from gfan of a
     656           polyhedral fan.
     657        -  ``polynomial_system`` - a list of polynomials
     658        -  ``poly_ring`` - the polynomial ring of the list of polynomials
     659        -  ``parameters`` (optional) - a list of variables to be considered as parameters
     660       
     661        EXAMPLES::
     662       
     663            sage: R.<x,y,z> = QQ[]
     664            sage: I = R.ideal([(x+y+z)^2-1,(x+y+z)-x,(x+y+z)-3])
     665            sage: GF = I.groebner_fan()
     666            sage: TI = GF.tropical_intersection()
     667            sage: TI._polynomial_system
     668            [x^2 + 2*x*y + y^2 + 2*x*z + 2*y*z + z^2 - 1, y + z, x + y + z - 3]
     669        """
     670        parameter_indices = []
     671        if parameters != []:
     672            allvars = poly_ring.gens()
     673            parameter_indices = [allvars.index(q) for q in parameters]
     674        PolyhedralFan.__init__(self, gfan_polyhedral_fan, parameter_indices = parameter_indices)
     675        self._polynomial_system = polynomial_system
     676        self._parameters = parameters
     677       
     678    def initial_form_systems(self):
     679        """
     680        Returns a list of systems of initial forms for each cone
     681        in the tropical prevariety.
     682
     683        EXAMPLES::
     684
     685            sage: R.<x,y> = QQ[]
     686            sage: I = R.ideal([(x+y)^2-1,(x+y)^2-2,(x+y)^2-3])
     687            sage: GF = I.groebner_fan()
     688            sage: PF = GF.tropical_intersection()
     689            sage: pfi = PF.initial_form_systems()
     690            sage: for q in pfi:
     691            ...     print q.initial_forms()
     692            [y^2 - 1, y^2 - 2, y^2 - 3]
     693            [x^2 - 1, x^2 - 2, x^2 - 3]
     694            [x^2 + 2*x*y + y^2, x^2 + 2*x*y + y^2, x^2 + 2*x*y + y^2]
     695        """
     696        try:
     697            return self._initial_form_systems
     698        except AttributeError:
     699            initial_form_systems = []
     700            pvars = self._polynomial_system[0].parent().gens()
     701            nvars = len(pvars)
     702            for dcone in self.cones():
     703                for acone in self.cones()[dcone]:
     704                    rays = [self.rays()[i] for i in acone]
     705                    repray = sum([vector(q) for q in rays])
     706                    iforms = []
     707                    for poly in self._polynomial_system:
     708                        verts = verts_for_normal(repray, poly)
     709                        nform = 0
     710                        for x in verts:   
     711                            factorlist = [pvars[i]**x[i] for i in range(nvars)]
     712                            temp_monomial = prod(factorlist)
     713                            nform += poly.monomial_coefficient(temp_monomial)*temp_monomial
     714                        iforms.append(nform)
     715                    initial_form_systems.append(InitialForm(acone, rays, iforms))
     716            self._initial_form_systems = initial_form_systems
     717            return self._initial_form_systems
     718
     719def ring_to_gfan_format(input_ring):
     720    """
     721    Converts a ring to gfan's format.
     722
     723    EXAMPLES::
     724
     725        sage: R.<w,x,y,z> = QQ[]
     726        sage: from sage.rings.polynomial.groebner_fan import ring_to_gfan_format
     727        sage: ring_to_gfan_format(R)
     728        'Q[w, x, y, z]'
     729        sage: R2.<x,y> = GF(2)[]
     730        sage: ring_to_gfan_format(R2)
     731        'Z/2Z[x, y]'
     732    """
     733    if input_ring.base_ring() == QQ:
     734        ring_str = 'Q' + str(input_ring.gens()).replace('(','[').replace(')',']')
     735    elif input_ring.base_ring() == ZZ:
     736        ring_str = 'Z' + str(input_ring.gens()).replace('(','[').replace(')',']')
     737    else:
     738        ring_str = 'Z/' + str(input_ring.characteristic()) + 'Z'+ str(input_ring.gens()).replace('(','[').replace(')',']')
     739    return ring_str
     740
     741def ideal_to_gfan_format(input_ring, polys):
     742    """
     743    Return the ideal in gfan's notation.
     744       
     745        EXAMPLES::
     746       
     747            sage: R.<x,y,z> = PolynomialRing(QQ,3)
     748            sage: polys = [x^2*y - z, y^2*z - x, z^2*x - y]
     749            sage: from sage.rings.polynomial.groebner_fan import ideal_to_gfan_format
     750            sage: ideal_to_gfan_format(R, polys)
     751            'Q[x, y, z]{x^2*y-z,y^2*z-x,x*z^2-y}'
     752    """
     753    ideal_gen_str = '{' + (str(polys).replace(' ', '').replace("'",""))[1:-1] + '}'
     754    ring_str = ring_to_gfan_format(input_ring)
     755    output = ring_str + ideal_gen_str
     756    return output
    415757
    416758class GroebnerFan(SageObject):
    417759   
    418760    def __init__(self, I, is_groebner_basis=False, symmetry=None, verbose=False):
    419761        """
     762        This class is used to access capabilities of the program Gfan.  In
     763        addition to computing Groebner fans, Gfan can compute other things in
     764        tropical geometry such as tropical prevarieties.
     765       
    420766        INPUT:
    421767       
    422768       
     
    435781       
    436782        EXAMPLES::
    437783       
    438             sage: R.<x,y,z> = PolynomialRing(QQ, 3, order='lex')
     784            sage: R.<x,y,z> = QQ[]
    439785            sage: I = R.ideal([x^2*y - z, y^2*z - x, z^2*x - y])
    440786            sage: G = I.groebner_fan(); G
    441787            Groebner fan of the ideal:
    442             Ideal (x^2*y - z, -x + y^2*z, x*z^2 - y) of Multivariate Polynomial Ring in x, y, z over Rational Field
     788            Ideal (x^2*y - z, y^2*z - x, x*z^2 - y) of Multivariate Polynomial Ring in x, y, z over Rational Field
     789           
     790        Here is an example of the use of the tropical_intersection command, and then using the RationalPolyhedralFan
     791        class to compute the Stanley-Reisner ideal of the tropical prevariety::
     792
     793            sage: R.<x,y,z> = QQ[]
     794            sage: I = R.ideal([(x+y+z)^3-1,(x+y+z)^3-x,(x+y+z)-3])
     795            sage: GF = I.groebner_fan()
     796            sage: PF = GF.tropical_intersection()
     797            sage: PF.rays()
     798            [[-1, 0, 0], [0, -1, 0], [0, 0, -1], [1, 1, 1]]
     799            sage: RPF = PF.to_RationalPolyhedralFan()
     800            sage: RPF.Stanley_Reisner_ideal(PolynomialRing(QQ,4,'A, B, C, D'))
     801            Ideal (A*B, A*C, B*C*D) of Multivariate Polynomial Ring in A, B, C, D over Rational Field
     802
    443803        """
    444804        self.__is_groebner_basis = is_groebner_basis
    445805        self.__symmetry = symmetry
     
    452812            raise RuntimeError, "Ring variables cannot contain each other as prefixes"
    453813        S = I.ring()
    454814        R = S.base_ring()
     815        # todo: add support for ZZ, which only works for bases computation, not tropical intersections
    455816        if not R.is_field():
    456817            raise NotImplementedError, "Groebner fan computation only implemented over fields"
    457818        if not (R is QQ or (R.is_finite() and R.is_prime_field() and R.order() <= 32749)):
     
    566927            sage: G._gfan_ring()
    567928            'Q[x, y, z]'
    568929        """
    569         if self.__ideal.base_ring() == QQ:
    570             ring_str = 'Q' + str(self.__ideal.ring().gens()).replace('(','[').replace(')',']')
    571         else:
    572             ring_str = 'Z/' + str(self.__ideal.base_ring().characteristic()) + 'Z'+ str(self.__ideal.ring().gens()).replace('(','[').replace(')',']')
    573         return ring_str
     930        return ring_to_gfan_format(self.ring())
    574931   
    575932    def _gfan_ideal(self):
    576933        """
     
    586943        try:
    587944            return self.__gfan_ideal
    588945        except AttributeError:
    589             ideal_gen_str = '{' + (str(self.__ideal.gens()).replace(' ', '').replace("'",""))[1:-1] + '}'
    590             ring_str = self._gfan_ring()
    591             self.__gfan_ideal = ring_str + ideal_gen_str
     946            self.__gfan_ideal = ideal_to_gfan_format(self.ring(),self.__ideal.gens())
    592947            return self.__gfan_ideal
    593948
    594949    def weight_vectors(self):
     
    601956            sage: r3.<x,y,z> = PolynomialRing(QQ,3)
    602957            sage: g = r3.ideal([x^3+y,y^3-z,z^2-x]).groebner_fan()
    603958            sage: g.weight_vectors()
    604             [(3, 7, 1), (5, 1, 2), (7, 1, 4), (1, 1, 4), (1, 1, 1), (1, 4, 1), (1, 4, 10)]
     959            [(3, 7, 1), (5, 1, 2), (7, 1, 4), (5, 1, 4), (1, 1, 1), (1, 4, 8), (1, 4, 10)]
    605960            sage: r4.<x,y,z,w> = PolynomialRing(QQ,4)
    606961            sage: g4 = r4.ideal([x^3+y,y^3-z,z^2-x,z^3 - w]).groebner_fan()
    607962            sage: len(g4.weight_vectors())
     
    641996        try:
    642997            return self.__gfan_reduced_groebner_bases
    643998        except AttributeError:
    644             B = self.gfan()
     999            B = self.gfan(cmd='bases')
    6451000            B = B.replace('\n','')
    6461001            self.__gfan_reduced_groebner_bases = B
    6471002            return B
     
    7181073            return self.__gfan_mod
    7191074        except AttributeError:
    7201075            mod = ''
    721             p = self.characteristic()
    722             if p != 0:
    723                 mod += ' --mod %s'%p
    724             else:
    725                 mod += ''
     1076            #p = self.characteristic()
     1077            #if p != 0:
     1078            #    mod += ' --mod %s'%p
     1079            #else:
     1080            #    mod += ''
    7261081
    7271082            if self.__is_groebner_basis:
    7281083                mod += ' -g'
     
    7331088            self.__gfan_mod = mod
    7341089            return self.__gfan_mod
    7351090
    736     def gfan(self, cmd='', I=None, format=True):
     1091    def gfan(self, cmd='bases', I=None, format=True):
    7371092        r"""
    7381093        Returns the gfan output as a string given an input cmd; the default
    7391094        is to produce the list of reduced Groebner bases in gfan format.
     
    11281483            sage: R.<x,y> = PolynomialRing(QQ)
    11291484            sage: G = R.ideal([y^3 - x^2, y^2 - 13*x]).groebner_fan()
    11301485            sage: G._gfan_stats()
    1131             {'Number of reduced Groebner bases': 3,
    1132              'Maximal total degree of a Groebner basis': 4,
    1133              'Dimension of homogeneity space': 0,
    1134              'Number of variables': 2,
    1135              'Minimal total degree of a Groebner basis': 2}
     1486            {'Number of reduced Groebner bases': 3, 'Number of variables': 2, 'Maximal number of terms in Groebner basis': 6, 'Minimal total degree of a Groebner basis': 2, 'Maximal total degree of a Groebner basis': 4, 'Maximal number of polynomials in Groebner basis': 3, 'Dimension of homogeneity space': 0}
    11361487        """
    11371488        try:
    11381489            return self.__stats
     
    12801631        """
    12811632        self[0].interactive(*args, **kwds)
    12821633
    1283     def tropical_intersection(self, ideal_arg = False, *args, **kwds):
     1634    def tropical_intersection(self, parameters = [], symmetry_generators = [], *args, **kwds):
    12841635        """
    12851636        Returns information about the tropical intersection of the
    1286         polynomials defining the ideal.
     1637        polynomials defining the ideal.  This is the common refinement
     1638        of the outward-pointing normal fans of the Newton polytopes of
     1639        the generators of the ideal. Note that some people use the
     1640        inward-pointing normal fans.
     1641
     1642        INPUT:
     1643
     1644        - ``parameters`` (optional) - a list of variables to be considered as parameters
     1645        - ``symmetry_generators`` (optional) - generators of the symmetry group
     1646
     1647        OUTPUT: a TropicalPrevariety object
    12871648       
    12881649        EXAMPLES::
    12891650       
    12901651            sage: R.<x,y,z> = PolynomialRing(QQ,3)
    1291             sage: i1 = ideal(x*z + 6*y*z - z^2, x*y + 6*x*z + y*z - z^2, y^2 + x*z + y*z)
    1292             sage: gf = i1.groebner_fan()
     1652            sage: I = R.ideal(x*z + 6*y*z - z^2, x*y + 6*x*z + y*z - z^2, y^2 + x*z + y*z)
     1653            sage: gf = I.groebner_fan()
    12931654            sage: pf = gf.tropical_intersection()
    12941655            sage: pf.rays()
    12951656            [[-2, 1, 1]]
     1657
     1658            sage: R.<x,y,z> = PolynomialRing(QQ,3)
     1659            sage: f1 = x*y*z - 1
     1660            sage: f2 = f1*(x^2 + y^2 + z^2)
     1661            sage: f3 = f2*(x + y + z - 1)
     1662            sage: I = R.ideal([f1,f2,f3])
     1663            sage: gf = I.groebner_fan()
     1664            sage: pf = gf.tropical_intersection(symmetry_generators = '(1,2,0),(1,0,2)')
     1665            sage: pf.rays()
     1666            [[-2, 1, 1], [1, -2, 1], [1, 1, -2]]
     1667
     1668            sage: R.<x,y,z> = QQ[]
     1669            sage: I = R.ideal([(x+y+z)^2-1,(x+y+z)-x,(x+y+z)-3])
     1670            sage: GF = I.groebner_fan()
     1671            sage: TI = GF.tropical_intersection()
     1672            sage: TI.rays()
     1673            [[-1, 0, 0], [0, -1, -1], [1, 1, 1]]
     1674            sage: GF = I.groebner_fan()
     1675            sage: TI = GF.tropical_intersection(parameters=[y])
     1676            sage: TI.rays()
     1677            [[-1, 0, 0]]
    12961678        """
    12971679        try:
    12981680            return self.__tropical_intersection
    12991681        except AttributeError:
    1300             f = self.gfan(cmd='tropicalintersection', I = self._gfan_ideal())
    1301             pf = PolyhedralFan(f)
     1682            cmd = 'tropicalintersection'
     1683            id_str = self._gfan_ideal()
     1684            if parameters != []:
     1685                allvars = self.ring().gens()
     1686                truevars = [q for q in allvars if not q in parameters]
     1687                base_ring = self.ring().base_ring()
     1688                new_ring = PolynomialRing(base_ring, len(truevars), string.join([str(q) for q in truevars], sep=','))
     1689                old_polys = self.ideal().gens()
     1690                new_polys = []
     1691                sub = dict([[v,1] for v in parameters])
     1692                for apoly in old_polys:
     1693                    mons = apoly.monomials()
     1694                    mons = [m.subs(sub) for m in mons]
     1695                    new_polys.append(sum(mons))
     1696                id_str = ideal_to_gfan_format(new_ring, new_polys)
     1697            if symmetry_generators != []:
     1698                cmd = cmd + ' --symmetryExploit'
     1699                id_str = id_str + '{' + symmetry_generators + '}'
     1700            f = self.gfan(cmd=cmd, I = id_str)
     1701            pf = TropicalPrevariety(f,self.ideal().gens(), self.ring(), parameters = parameters)
     1702            pf._gfan_output = f
    13021703            self.__tropical_intersection = pf
    13031704            return pf
    13041705       
     1706
     1707    def mixed_volume(self):
     1708        """
     1709        Returns the mixed volume of the generators of this ideal (i.e. this is
     1710        not really an ideal property, it can depend on the generators used).
     1711        The generators must give a square system (as many polynomials as variables).
     1712
     1713        EXAMPLES::
    13051714       
     1715            sage: R.<x,y,z> = QQ[]
     1716            sage: example_ideal = R.ideal([x^2-y-1,y^2-z-1,z^2-x-1])
     1717            sage: gf = example_ideal.groebner_fan()
     1718            sage: mv = gf.mixed_volume()
     1719            sage: mv
     1720            8
     1721   
     1722            sage: R2.<x,y> = QQ[]
     1723            sage: g1 = 1 - x + x^7*y^3 + 2*x^8*y^4
     1724            sage: g2 = 2 + y + 3*x^7*y^3 + x^8*y^4
     1725            sage: example2 = R2.ideal([g1,g2])
     1726            sage: example2.groebner_fan().mixed_volume()
     1727            15
     1728        """
     1729        if len(self.ring().variable_names()) != self.ideal().ngens():
     1730            raise UserWarning, 'not a square system'
     1731        return Integer(self.gfan(cmd='mixedvolume'))
    13061732
    13071733class ReducedGroebnerBasis(SageObject, list):
    13081734    def __init__(self, groebner_fan, gens, gfan_gens):