Ticket #11316: trac_11316.3.patch

File trac_11316.3.patch, 76.2 KB (added by klee, 10 years ago)

rebased to Sage 4.7; replaced double underscored attributes to single underscored ones

  • sage/crypto/mq/sr.py

    # HG changeset patch
    # User Kwankyu Lee <ekwankyu@gmail.com>
    # Date 1305014300 -32400
    # Node ID c14df15c273dd4d2707c69a24c5ee3fa5ff1d008
    # Parent  ce324e28c3334398d3552640e2cb1520d22465a3
    #11316: added weighted degree term orders
    
    diff -r ce324e28c333 -r c14df15c273d sage/crypto/mq/sr.py
    a b  
    16651665       
    16661666            sage: sr = mq.SR(2, 1, 1, 4)
    16671667            sage: sr.block_order()
    1668             degrevlex(16),degrevlex(16),degrevlex(4) term order
     1668            Block term order with blocks:
     1669            (Degree reverse lexicographic term order of length 16,
     1670             Degree reverse lexicographic term order of length 16,
     1671             Degree reverse lexicographic term order of length 4)
    16691672       
    16701673        ::
    16711674       
  • sage/libs/singular/ring.pyx

    diff -r ce324e28c333 -r c14df15c273d sage/libs/singular/ring.pyx
    a b  
    2222from sage.libs.singular.decl cimport number, lnumber, napoly, ring, currRing
    2323from sage.libs.singular.decl cimport rChangeCurrRing, rCopy0, rComplete, rDelete
    2424from sage.libs.singular.decl cimport omAlloc0, omStrDup, omAlloc, omAlloc0Bin,  sip_sring_bin, rnumber_bin
    25 from sage.libs.singular.decl cimport ringorder_dp, ringorder_Dp, ringorder_lp, ringorder_rp, ringorder_ds, ringorder_Ds, ringorder_ls, ringorder_M, ringorder_C
     25from sage.libs.singular.decl cimport ringorder_dp, ringorder_Dp, ringorder_lp, ringorder_rp, ringorder_ds, ringorder_Ds, ringorder_ls, ringorder_M, ringorder_C, ringorder_wp, ringorder_Wp, ringorder_ws, ringorder_Ws
    2626from sage.libs.singular.decl cimport p_Copy
    2727
    2828from sage.rings.integer cimport Integer
     
    4141
    4242
    4343# mapping str --> SINGULAR representation
    44 order_dict = {"dp":ringorder_dp,
    45               "Dp":ringorder_Dp,
    46               "lp":ringorder_lp,
    47               "rp":ringorder_rp,
    48               "ds":ringorder_ds,
    49               "Ds":ringorder_Ds,
    50               "ls":ringorder_ls,
    51               }
     44order_dict = {
     45    "dp": ringorder_dp,
     46    "Dp": ringorder_Dp,
     47    "lp": ringorder_lp,
     48    "rp": ringorder_rp,
     49    "ds": ringorder_ds,
     50    "Ds": ringorder_Ds,
     51    "ls": ringorder_ls,
     52    "wp": ringorder_wp,
     53    "Wp": ringorder_Wp,
     54    "ws": ringorder_ws,
     55    "Ws": ringorder_Ws,
     56}
    5257
    5358cdef ring *singular_ring_new(base_ring, n, names, term_order) except NULL:
    5459    """
     
    236241
    237242        _ring.minpoly=<number*>nmp
    238243
    239     nblcks = len(order.blocks)
     244    nblcks = len(order.blocks())
    240245    offset = 0
    241246
    242247    _ring.wvhdl  = <int **>omAlloc0((nblcks + 2) * sizeof(int *))
     
    250255        _ring.OrdSgn = 1
    251256
    252257    for i from 0 <= i < nblcks:
    253         if order[i].singular_str()[0] == 'M':
     258        s = order[i].singular_str()
     259        if s[0] == 'M': # matrix order
    254260            _ring.order[i] = ringorder_M
    255261            mtx = order[i].matrix().list()
    256             m = <int *>omAlloc0(len(mtx)*sizeof(int))
     262            wv = <int *>omAlloc0(len(mtx)*sizeof(int))
    257263            for j in range(len(mtx)):
    258                 m[j] = int(mtx[j])
    259             _ring.wvhdl[i] = m
    260         else:
    261             _ring.order[i] = order_dict.get(order[i].singular_str(), ringorder_dp)
     264                wv[j] = int(mtx[j])
     265            _ring.wvhdl[i] = wv
     266        elif s[0] == 'w' or s[0] == 'W': # weighted degree orders
     267            _ring.order[i] = order_dict.get(s[:2], ringorder_dp)
     268            wts = order[i].weights()
     269            wv = <int *>omAlloc0(len(wts)*sizeof(int))
     270            for j in range(len(wts)):
     271                wv[j] = int(wts[j])
     272            _ring.wvhdl[i] = wv   
     273        else: # ordinary orders
     274            _ring.order[i] = order_dict.get(s, ringorder_dp)
    262275        _ring.block0[i] = offset + 1
    263276        if len(order[i]) == 0: # may be zero in some cases
    264277            _ring.block1[i] = offset + n
  • sage/rings/polynomial/multi_polynomial_ring.py

    diff -r ce324e28c333 -r c14df15c273d sage/rings/polynomial/multi_polynomial_ring.py
    a b  
    468468            c = self.base_ring()(x)
    469469            return MPolynomial_polydict(self, {self._zero_tuple:c})
    470470
    471 
    472 
    473471class MPolynomialRing_polydict_domain(integral_domain.IntegralDomain,
    474472                                      MPolynomialRing_polydict,
    475473                                      MPolynomialRing_macaulay2_repr):
    476474    def __init__(self, base_ring, n, names, order):
    477         order = TermOrder(order, n)
     475        order = TermOrder(order,n) 
    478476        MPolynomialRing_polydict.__init__(self, base_ring, n, names, order)
    479477
    480478    def is_integral_domain(self, proof = True):
     
    513511            gens = [self(x) for x in gens]  # this will even coerce from singular ideals correctly!
    514512        return multi_polynomial_ideal.MPolynomialIdeal(self, gens, **kwds)
    515513
    516 
    517514    def monomial_quotient(self,f, g, coeff=False):
    518515        """
    519516        Return f/g, where both f and g are treated as monomials.
     
    716713                return 0,0
    717714        return 0,0
    718715
    719 
    720716    def monomial_divides(self, a, b):
    721717        """
    722718        Return False if a does not divide b and True otherwise.
  • sage/rings/polynomial/multi_polynomial_ring_generic.pyx

    diff -r ce324e28c333 -r c14df15c273d sage/rings/polynomial/multi_polynomial_ring_generic.pyx
    a b  
    4848            sage: A1(a) in A2
    4949            True
    5050        """
    51         order = TermOrder(order,n)
     51        order = TermOrder(order,n) 
     52
    5253        if not base_ring.is_commutative():
    5354            raise TypeError, "Base ring must be a commutative ring."
    5455        n = int(n)
     
    252253        _repr += "       Size : %d Variables\n"%(n,)
    253254        offset = 0
    254255        i = 0
    255         for order in T.blocks:
     256        for order in T.blocks():
    256257            _repr += "   Block % 2d : Ordering : %s\n"%(i,inv_singular_name_mapping.get(order.singular_str(), order.singular_str()))
    257258            _repr += "              Names    : %s\n"%(", ".join(names[offset:offset + len(order)]))
    258259            offset += len(order)
  • sage/rings/polynomial/pbori.pyx

    diff -r ce324e28c333 -r c14df15c273d sage/rings/polynomial/pbori.pyx
    a b  
    263263
    264264        sage: R = BooleanPolynomialRing(5,'x',order='deglex(3),deglex(2)')
    265265        sage: R.term_order()
    266         deglex(3),deglex(2) term order
     266        Block term order with blocks:
     267        (Degree lexicographic term order of length 3,
     268         Degree lexicographic term order of length 2)
    267269
    268270    ::
    269271
     
    326328        except KeyError:
    327329            raise ValueError, "Only lex, deglex, degrevlex orders are supported."
    328330
    329         if len(order.blocks) > 1:
     331        if order.is_block_order():
    330332            if pb_order_code is pblp:
    331333                raise ValueError, "Only deglex and degrevlex are supported for block orders."
    332334            elif pb_order_code is pbdlex:
    333335                pb_order_code = pbblock_dlex
    334336            elif pb_order_code is pbdp_asc:
    335337                pb_order_code = pbblock_dp_asc
    336             for i in range(1, len(order.blocks)):
    337                 if order[0] != order[i]:
    338                     raise ValueError, "Each block must have the same order type (deglex or degrevlex) for block orderings."
     338            for i in range(1, len(order.blocks())):
     339                if order[0].name() != order[i].name():
     340                    raise ValueError, "Each block must have the same order type (deglex or degrevlex) for block orders."
    339341
    340342        if (pb_order_code is pbdlex) or (pb_order_code is pblp) or \
    341343                (pb_order_code is pbblock_dlex):
     
    347349        else:
    348350            # pb_order_code is block_dp_asc:
    349351            bstart = 0
    350             for i from 0 <= i < len(order.blocks):
     352            for i from 0 <= i < len(order.blocks()):
    351353                bsize = len(order[i])
    352354                for j from 0 <= j < bsize:
    353355                    self.pbind[bstart + j] = bstart + bsize - j -1
     
    357359        MPolynomialRing_generic.__init__(self, GF(2), n, names, order)
    358360
    359361        counter = 0
    360         for i in range(len(order.blocks)-1):
     362        for i in range(len(order.blocks())-1):
    361363            counter += len(order[i])
    362364            pb_append_block(counter)
    363365
     
    70567058        sage: change_ordering(block_dp_asc)
    70577059        sage: append_ring_block(5)
    70587060        sage: get_cring().term_order()
    7059         deglex_asc(5),deglex_asc(5) term order
     7061        Block term order with blocks:
     7062        (deglex_asc term order of length 5,
     7063         deglex_asc term order of length 5) 
    70607064        sage: change_ordering(lp)
    70617065 
    70627066        sage: from polybori.blocks import *
     
    71297133    else:
    71307134        # pb_order_code is block_dp_asc:
    71317135        bstart = 0
    7132         for i from 0 <= i < len(T.blocks):
     7136        for i from 0 <= i < len(T.blocks()):
    71337137            bsize = len(T[i])
    71347138            for j from 0 <= j < bsize:
    71357139                self.pbind[bstart + j] = bstart + j
  • sage/rings/polynomial/polynomial_ring.py

    diff -r ce324e28c333 -r c14df15c273d sage/rings/polynomial/polynomial_ring.py
    a b  
    688688            except AttributeError:
    689689                return self.base_ring()
    690690       
    691            
    692691    def characteristic(self):
    693692        """
    694693        Return the characteristic of this polynomial ring, which is the
  • sage/rings/polynomial/polynomial_ring_constructor.py

    diff -r ce324e28c333 -r c14df15c273d sage/rings/polynomial/polynomial_ring_constructor.py
    a b  
    494494
    495495        sage: R = BooleanPolynomialRing(5,'x',order='deglex(3),deglex(2)')
    496496        sage: R.term_order()
    497         deglex(3),deglex(2) term order
     497        Block term order with blocks:
     498        (Degree lexicographic term order of length 3,
     499         Degree lexicographic term order of length 2)
    498500
    499501        sage: R = BooleanPolynomialRing(3,'x',order='degrevlex')
    500502        sage: R.term_order()
     
    531533
    532534    from sage.rings.polynomial.term_order import TermOrder
    533535    from sage.rings.polynomial.pbori import set_cring
     536
    534537    order = TermOrder(order, n)
    535538
    536539    key = ("pbori", names, n, order)
  • sage/rings/polynomial/term_order.py

    diff -r ce324e28c333 -r c14df15c273d sage/rings/polynomial/term_order.py
    a b  
    11r"""
    2 Term Orderings
     2Term orders
    33
    4 Sage supports the following term orderings:
     4Sage supports the following term orders:
    55
    6 Lexicographic (*lex*)
    7     `x^a < x^b \Leftrightarrow \exists\; 0 \le i < n : a_0 = b_0, \ldots, a_{i-1} = b_{i-1}, a_i < b_i`
     6Lexicographic (lex)
     7    `x^a < x^b` if and only if there exists `1 \le i \le n` such that `a_1 = b_1, \dots, a_{i-1} = b_{i-1}, a_i < b_i`. 
     8    This term order is called 'lp' in Singular.
    89
    910    EXAMPLES:
    1011
     
    2223        sage: x^3*y^2*z^4 < x^3*y^2*z^1
    2324        False
    2425
    25     This term ordering is called 'lp' in Singular.
    26 
    27 Degree reverse lexicographic (*degrevlex*)
    28     Let `deg(x^a) = a_0 + \cdots + a_{n-1},` then
    29     `x^a < x^b \Leftrightarrow deg(x^a) < deg(x^b)` or
    30     `deg(x^a) = deg(x^b)` and
    31     `\exists\ 0 \le i < n: a_{n-1} = b_{n-1}, \ldots, a_{i+1} = b_{i+1}, a_i > b_i.`
     26Degree reverse lexicographic (degrevlex)
     27    Let `\deg(x^a) = a_1 + a_2 + \dots + a_n`, then
     28    `x^a < x^b` if and only if `\deg(x^a) < \deg(x^b)` or `\deg(x^a) = \deg(x^b)` and 
     29    there exists `1 \le i \le n` such that `a_n = b_n, \dots, a_{i+1} = b_{i+1}, a_i > b_i`. 
     30    This term order is called 'dp' in Singular.   
    3231
    3332    EXAMPLES:
    3433
     
    4645        sage: x^2*y*z^2 > x*y^3*z
    4746        False
    4847
    49     This term ordering is called 'dp' in Singular.
    50 
    51 Degree lexicographic (*deglex*)
    52     Let `deg(x^a) = a_0 + \cdots + a_{n-1},` then
    53     `x^a < x^b \Leftrightarrow deg(x^a) < deg(x^b)` or
    54     `deg(x^a) = deg(x^b)` and
    55     `\exists\ 0 \le i < n:a_0 = b_0, \ldots, a_{i-1} = b_{i-1}, a_i < b_i.`
     48Degree lexicographic (deglex)
     49    Let `\deg(x^a) = a_1 + a_2 + \dots + a_n`, then
     50    `x^a < x^b` if and only if `\deg(x^a) < \deg(x^b)` or `\deg(x^a) = \deg(x^b)` and 
     51    there exists `1 \le i \le n` such that `a_1 = b_1, \dots, a_{i-1} = b_{i-1}, a_i < b_i`. 
     52    This term order is called 'Dp' in Singular.
    5653
    5754    EXAMPLES:
    5855
     
    7067        sage: x^2*y*z^2 > x*y^3*z
    7168        True
    7269
    73     This term order is called 'Dp' in Singular.
    74 
    75 Inverse lexicographic (*invlex*)
    76     `x^a < x^b \Leftrightarrow \exists\; 0 \le i < n : a_{n-1} = b_{n-1}, \ldots, a_{i+1} = b_{i+1}, a_i < b_i.`
     70Inverse lexicographic (invlex)
     71    `x^a < x^b` if and only if there exists `1 \le i \le n` such that `a_n = b_n, \dots, a_{i+1} = b_{i+1}, a_i < b_i`.
     72    This order is called 'rp' in Singular.
    7773
    7874    EXAMPLES:
    7975
     
    8985        sage: x*y > z
    9086        False
    9187
    92     This term ordering only makes sense in a non-commutative setting
     88    This term order only makes sense in a non-commutative setting
    9389    because if P is the ring `k[x_1, \dots, x_n]` and term
    94     ordering 'invlex' then it is equivalent to the ring
    95     `k[x_n, \dots, x_1]` with term ordering 'lex'.
     90    order 'invlex' then it is equivalent to the ring
     91    `k[x_n, \dots, x_1]` with term order 'lex'.
    9692
    97     This ordering is called 'rp' in Singular.
    98 
    99 Negative lexicographic (*neglex*)
    100     `x^a < x^b \Leftrightarrow \exists\; 0 \le i < n : a_0 = b_0, \ldots, a_{i-1} = b_{i-1}, a_i > b_i`
     93Negative lexicographic (neglex)
     94    `x^a < x^b` if and only if there exists `1 \le i \le n` such that `a_1 = b_1, \dots, a_{i-1} = b_{i-1}, a_i > b_i`.   
     95    This term order is called 'ls' in Singular.
    10196
    10297    EXAMPLES:
    10398
     
    115110        sage: x*y > z
    116111        False
    117112
    118     This term ordering is called 'ls' in Singular.
    119 
    120 Negative degree reverse lexicographic (*negdegrevlex*)
    121     Let `deg(x^a) = a_0 + \cdots + a_{n-1},` then
    122     `x^a < x^b \Leftrightarrow deg(x^a) > deg(x^b)` or
    123     `deg(x^a) = deg(x^b)` and
    124     `\exists\ 0 \le i < n: a_{n-1} = b_{n-1}, \ldots, a_{i+1} = b_{i+1}, a_i > b_i.`
     113Negative degree reverse lexicographic (negdegrevlex)
     114    Let `\deg(x^a) = a_1 + a_2 + \dots + a_n`, then
     115    `x^a < x^b` if and only if `\deg(x^a) > \deg(x^b)` or `\deg(x^a) = \deg(x^b)` and 
     116    there exists `1 \le i \le n` such that `a_n = b_n, \dots, a_{i+1} = b_{i+1}, a_i > b_i`. 
     117    This term order is called 'ds' in Singular.
    125118
    126119    EXAMPLES:
    127120
     
    139132        sage: x^2*y*z^2 > x*y^3*z
    140133        False
    141134
    142     This term ordering is called 'ds' in Singular.
    143 
    144 Negative degree lexicographic (*negdeglex*)
    145     Let `deg(x^a) = a_0 + \cdots + a_{n-1},` then
    146     `x^a < x^b \Leftrightarrow deg(x^a) > deg(x^b)` or
    147     `deg(x^a) = deg(x^b)` and
    148     `\exists\ 0 \le i < n: a_0 = b_0, \ldots, a_{i-1} = b_{i-1}, a_i < b_i.`
     135Negative degree lexicographic (negdeglex)
     136    Let `\deg(x^a) = a_1 + a_2 + \dots + a_n`, then
     137    `x^a < x^b` if and only if `\deg(x^a) > \deg(x^b)` or `\deg(x^a) = \deg(x^b)` and
     138    there exists `1 \le i \le n` such that `a_1 = b_1, \dots, a_{i-1} = b_{i-1}, a_i < b_i`. 
     139    This term order is called 'Ds' in Singular.
    149140
    150141    EXAMPLES:
    151142
     
    163154        sage: x^2*y*z^2 > x*y^3*z
    164155        True
    165156
    166     This term ordering is called 'Ds' in Singular.
     157Weighted degree reverse lexicographic (wdegrevlex)
     158    Let `\deg_w(x^a) = a_1w_1 + a_2w_2 + \dots + a_nw_n` with weights `w`, then
     159    `x^a < x^b` if and only if `\deg_w(x^a) < \deg_w(x^b)` or `\deg_w(x^a) = \deg_w(x^b)` and 
     160    there exists `1 \le i \le n` such that `a_n = b_n, \dots, a_{i+1} = b_{i+1}, a_i > b_i`.   
     161    This term order is called 'wp' in Singular.     
    167162
     163    EXAMPLES:
    168164
    169 Of these, only 'degrevlex', 'deglex', 'invlex' and 'lex' are global
    170 orderings.
     165    ::
    171166
    172 Additionally all these monomial orderings may be combined to
    173 product or block orderings, defined as:
     167        sage: P.<x,y,z> = PolynomialRing(QQ, 3, order=TermOrder('wdegrevlex',(1,2,3)))   
     168        sage: x > y
     169        False
     170        sage: x > x^2
     171        False
     172        sage: x > 1
     173        True
     174        sage: x^1*y^2 > x^2*z
     175        True
     176        sage: y*z > x^3*y
     177        False
    174178
    175 Let `x = (x_0, \ldots, x_{n-1})` and
    176 `y = (y_0, \ldots, y_{m-1})` be two ordered sets of
    177 variables, `<_1` a monomial ordering on `k[x]` and
    178 `<_2` a monomial ordering on `k[y]`.
     179Weighted degree lexicographic (wdeglex)
     180    Let `\deg_w(x^a) = a_1w_1 + a_2w_2 + \dots + a_nw_n` with weights `w`, then
     181    `x^a < x^b` if and only if `\deg_w(x^a) < \deg_w(x^b)` or `\deg_w(x^a) = \deg_w(x^b)` and
     182    there exists `1 \le i \le n` such that `a_1 = b_1, \dots, a_{i-1} = b_{i-1}, a_i < b_i`. 
     183    This term order is called 'Wp' in Singular.     
    179184
    180 The product ordering (or block ordering)
    181 `<\ := (<_1,<_2)` on `k[x,y]` is defined as:
    182 `x^a y^b < x^A y^B \Leftrightarrow x^a <_1 x^A` or
    183 `(x^a =x^A \textrm{ and } y^b <_2 y^B)`.
     185    EXAMPLES:
    184186
    185 These block orderings are constructed in Sage by giving a comma
    186 separated list of monomial orderings with the length of each block
    187 attached to them.
     187    ::
     188
     189        sage: P.<x,y,z> = PolynomialRing(QQ, 3, order=TermOrder('wdeglex',(1,2,3)))
     190        sage: x > y
     191        False
     192        sage: x > x^2
     193        False
     194        sage: x > 1
     195        True
     196        sage: x^1*y^2 > x^2*z
     197        False
     198        sage: y*z > x^3*y
     199        False
     200
     201Negative weighted degree reverse lexicographic (negwdegrevlex)
     202    Let `\deg_w(x^a) = a_1w_1 + a_2w_2 + \dots + a_nw_n` with weights `w`, then
     203    `x^a < x^b` if and only if `\deg_w(x^a) > \deg_w(x^b)` or `\deg_w(x^a) = \deg_w(x^b)` and 
     204    there exists `1 \le i \le n` such that `a_n = b_n, \dots, a_{i+1} = b_{i+1}, a_i > b_i`. 
     205    This term order is called 'ws' in Singular.     
     206
     207    EXAMPLES:
     208
     209    ::
     210
     211        sage: P.<x,y,z> = PolynomialRing(QQ, 3, order=TermOrder('negwdegrevlex',(1,2,3))) 
     212        sage: x > y
     213        True
     214        sage: x > x^2
     215        True
     216        sage: x > 1
     217        False
     218        sage: x^1*y^2 > x^2*z
     219        True
     220        sage: y*z > x^3*y
     221        False
     222
     223Negative weighted degree lexicographic (negwdeglex)
     224    Let `\deg_w(x^a) = a_1w_1 + a_2w_2 + \dots + a_nw_n` with weights `w`, then
     225    `x^a < x^b` if and only if `\deg_w(x^a) > \deg_w(x^b)` or `\deg_w(x^a) = \deg_w(x^b)` and
     226    there exists `1 \le i \le n` such that `a_1 = b_1, \dots, a_{i-1} = b_{i-1}, a_i < b_i`.   
     227    This term order is called 'Ws' in Singular.     
     228
     229    EXAMPLES:
     230
     231    ::
     232
     233        sage: P.<x,y,z> = PolynomialRing(QQ, 3, order=TermOrder('negwdeglex',(1,2,3)))     
     234        sage: x > y
     235        True
     236        sage: x > x^2
     237        True
     238        sage: x > 1
     239        False
     240        sage: x^1*y^2 > x^2*z
     241        False
     242        sage: y*z > x^3*y
     243        False
     244
     245Of these, only 'degrevlex', 'deglex', 'wdegrevlex', 'wdeglex', 'invlex' and 'lex' are global
     246orders.   
     247
     248Sage also supports matrix term order. Given a square matrix `A`,
     249
     250    `x^a <_A x^b` if and only if `Aa < Ab`
     251
     252where `<` is the lexicographic term order.
     253
     254EXAMPLE::
     255
     256    sage: m = matrix(2,[2,3,0,1]); m
     257    [2 3]
     258    [0 1]
     259    sage: T = TermOrder(m); T
     260    Matrix term order with matrix
     261    [2 3]
     262    [0 1]   
     263    sage: P.<a,b> = PolynomialRing(QQ,2,order=T)
     264    sage: P
     265    Multivariate Polynomial Ring in a, b over Rational Field
     266    sage: a > b
     267    False
     268    sage: a^3 < b^2
     269    True
     270    sage: S = TermOrder('M(2,3,0,1)')
     271    sage: T == S
     272    True   
     273
     274Additionally all these monomial orders may be combined to product or block orders, defined as:
     275
     276Let `x = (x_1, x_2, \dots, x_n)` and `y = (y_1, y_2, \dots, y_m)` be two ordered sets of
     277variables, `<_1` a monomial order on `k[x]` and `<_2` a monomial order on `k[y]`.
     278
     279The product order (or block order) `<` `:=` `(<_1,<_2)` on `k[x,y]` is defined as:
     280`x^a y^b < x^A y^B` if and only if `x^a <_1 x^A` or (`x^a =x^A` and `y^b <_2 y^B`).
     281
     282These block orders are constructed in Sage by giving a comma separated list of monomial orders
     283with the length of each block attached to them.
    188284
    189285EXAMPLE:
    190286
    191 As an example, consider constructing a block ordering where the
     287As an example, consider constructing a block order where the
    192288first four variables are compared using the degree reverse
    193 lexicographical ordering while the last two variables in the second
    194 block are compared using negative lexicographical ordering.
     289lexicographical order while the last two variables in the second
     290block are compared using negative lexicographical order.
    195291
    196292::
    197293
     
    214310    sage: a > e^4
    215311    True
    216312
    217 Finally Sage supports matrix term order. Given a square matrix `A`,
     313If any other unsupported term order is given the provided string
     314can be forced to be passed through as is to Singular, Macaulay2, and Magma.
     315This ensures that it is for example possible to calculate a Groebner
     316basis with respect to some term order Singular supports but Sage
     317doesn't::
    218318
    219     `x^a < x^b \Leftrightarrow x^{Aa} <_{\mathrm{lex}} x^{Ab}`
    220 
    221 where `<_{\mathrm{lex}}` is the lexicographic term order.
    222 
    223 EXAMPLE::
    224 
    225     sage: m = matrix(2,[2,3,0,1]); m
    226     [2 3]
    227     [0 1]
    228     sage: T = TermOrder(m); T
    229     Matrix term order with matrix
    230     [2 3]
    231     [0 1]   
    232     sage: P.<a,b> = PolynomialRing(QQ,2,order=T)
    233     sage: P
    234     Multivariate Polynomial Ring in a, b over Rational Field
    235     sage: a > b
    236     False
    237     sage: a^3 < b^2
    238     True
    239     sage: S = TermOrder('M(2,3,0,1)')
    240     sage: T == S
    241     True
    242 
    243 A matrix term ordering is not allowed in block ordering yet::
    244 
    245     sage: T+S
     319    sage: T = TermOrder("royalorder")
    246320    Traceback (most recent call last):
    247321    ...
    248     NotImplementedError: Cannot use a matrix term order as a block.
    249 
    250 If any other unsupported term ordering is given the provided string
    251 is passed through as is to Singular, Macaulay2, and Magma. This
    252 ensures that it is for example possible to calculate a Groebner
    253 basis with respect to some term ordering Singular supports but Sage
    254 doesn't. However a warning is issued to make the user aware of the
    255 situation and potential typos::
    256 
    257     sage: T = TermOrder("royalorder")
    258     verbose 0 (...: term_order.py, __init__) Term ordering 'royalorder' unknown.
    259 
     322    TypeError: Unknown term order 'royalorder'
     323    sage: T = TermOrder("royalorder",force=True)
     324    sage: T
     325    royalorder term order
     326    sage: T.singular_str()
     327    'royalorder'
     328   
    260329AUTHORS:
    261330
    262 - David Joyner and William Stein: initial version
    263   multi_polynomial_ring
     331- David Joyner and William Stein: initial version of multi_polynomial_ring
    264332
    265333- Kiran S. Kedlaya: added macaulay2 interface
    266334
    267 - Martin Albrecht: implemented native term orderings, refactoring
     335- Martin Albrecht: implemented native term orders, refactoring
    268336
    269 - Kwankyu Lee (2010-06): implemented matrix term ordering
     337- Kwankyu Lee: implemented matrix and weighted degree term orders, refactoring
    270338"""
    271339
    272 import re
    273 from sage.structure.sage_object import SageObject
     340import re 
     341from sage.structure.sage_object import SageObject   
    274342
    275343print_name_mapping = {
    276     'lex'          :'Lexicographic',
    277     'invlex'       :'Inverse Lexicographic',
    278     'degrevlex'    :'Degree reverse lexicographic',
    279     'deglex'       :'Degree lexicographic',
    280     'neglex'       :'Negative lexicographic',
    281     'negdegrevlex' :'Negative degree reverse lexicographic',
    282     'negdeglex'    :'Negative degree lexicographic'}
     344    'lex'           : 'Lexicographic',
     345    'invlex'        : 'Inverse lexicographic',
     346    'degrevlex'     : 'Degree reverse lexicographic',   
     347    'deglex'        : 'Degree lexicographic',       
     348    'neglex'        : 'Negative lexicographic',
     349    'negdegrevlex'  : 'Negative degree reverse lexicographic',
     350    'negdeglex'     : 'Negative degree lexicographic',
     351    'wdegrevlex'    : 'Weighted degree reverse lexicographic', 
     352    'wdeglex'       : 'Weighted degree lexicographic',
     353    'negwdegrevlex' : 'Negative weighted degree reverse lexicographic',
     354    'negwdeglex'    : 'Negative weighted degree lexicographic',       
     355}
    283356
    284357singular_name_mapping = {
    285     'lex'          :'lp',
    286     'invlex'       :'rp',
    287     'degrevlex'    :'dp',
    288     'deglex'       :'Dp',
    289     'neglex'       :'ls',
    290     'negdegrevlex' :'ds',
    291     'negdeglex'    :'Ds'}
     358    'lex'           : 'lp',
     359    'invlex'        : 'rp',
     360    'degrevlex'     : 'dp',
     361    'deglex'        : 'Dp',
     362    'neglex'        : 'ls',
     363    'negdegrevlex'  : 'ds',
     364    'negdeglex'     : 'Ds',
     365    'wdegrevlex'    : 'wp', 
     366    'wdeglex'       : 'Wp',
     367    'negwdegrevlex' : 'ws',
     368    'negwdeglex'    : 'Ws',     
     369}
    292370
    293 inv_singular_name_mapping = {
    294     'lp'           :'lex',
    295     'rp'           :'invlex',
    296     'dp'           :'degrevlex',
    297     'Dp'           :'deglex',
    298     'ls'           :'neglex',
    299     'ds'           :'negdegrevlex',
    300     'Ds'           :'negdeglex'}
     371inv_singular_name_mapping = dict(zip(singular_name_mapping.values(),singular_name_mapping.keys()))
    301372
    302373macaulay2_name_mapping = {
    303     'lex'          :'Lex',
    304     'revlex'       :'RevLex, Global=>false',
    305     'degrevlex'    :'GRevLex',
    306     'deglex'       :'GLex'}
     374    'lex'           : 'Lex',
     375    'revlex'        : 'RevLex, Global=>false',
     376    'degrevlex'     : 'GRevLex',
     377    'deglex'        : 'GLex',
     378}
    307379
    308 inv_macaulay2_name_mapping = {
    309     'Lex'          :'lex',
    310     'RevLex,Global=>false' :'revlex',
    311     'GRevLex'      :"degrevlex",
    312     'GLex'         :'deglex'}
     380inv_macaulay2_name_mapping = dict(zip(macaulay2_name_mapping.values(),macaulay2_name_mapping.keys()))
    313381
    314 magma_name_mapping =     {
    315     'lex'          :'"lex"',
    316     'degrevlex'    :'"grevlex"',
    317     'deglex'       :'"glex"'}
     382magma_name_mapping = {
     383    'lex'           : '"lex"',
     384    'degrevlex'     : '"grevlex"',
     385    'deglex'        : '"glex"',
     386}
    318387
    319 lp_description = """
    320 Lexicographic (lex) term ordering.
     388inv_magma_name_mapping = dict(zip(magma_name_mapping.values(),magma_name_mapping.keys()))
    321389
    322 $x^a < x^b <=> \exists\; 0 <= i < n : a_0 = b_0, ..., a_{i-1} = b_{i-1}, a_i < b_i$
     390lex_description = """
     391Lexicographic (lex) term order.
     392
     393`x^a < x^b` if and only if there exists `1 \le i \le n` such that `a_1 = b_1, \dots, a_{i-1} = b_{i-1}, a_i < b_i`. 
    323394"""
    324395
    325 dp_description = """
    326 Degree reverse lexicographic (degrevlex) term ordering.
     396invlex_description = """
     397Inverse lexicographic (invlex) term order.
    327398
    328 Let $deg(x^a) = a_0 + ... + a_{n-1},$ then $x^a < x^b <=> deg(x^a) < deg(x^b)$ or
    329 $deg(x^a) = deg(x^b)$ and $\exists\ 0 <= i < n: a_{n-1} = b_{n-1}, ..., a_{i+1} = b_{i+1}, a_i > b_i.$
     399`x^a < x^b` if and only if there exists `1 \le i \le n` such that `a_n = b_n, \dots, a_{i+1} = b_{i+1}, a_i < b_i`. 
     400""" 
     401
     402degrevlex_description = """
     403Degree reverse lexicographic (degrevlex) term order.
     404
     405Let `\deg(x^a) = a_1 + a_2 + \dots + a_n`, then
     406`x^a < x^b` if and only if `\deg(x^a) < \deg(x^b)` or `\deg(x^a) = \deg(x^b)` and 
     407there exists `1 \le i \le n` such that `a_n = b_n, \dots, a_{i+1} = b_{i+1}, a_i > b_i`.
    330408"""
    331409
    332 Dp_description = """
    333 Degree lexicographic (deglex) term ordering.
     410deglex_description = """
     411Degree lexicographic (deglex) term order.
    334412
    335 Let $deg(x^a) = a_0 + \cdots + a_{n-1},$ then $x^a < x^b \Leftrightarrow deg(x^a) < deg(x^b)$ or
    336 $deg(x^a) = deg(x^b)$ and $\exists\ 0 \le i < n:a_0 = b_0, \ldots, a_{i-1} = b_{i-1}, a_i < b_i.$
     413Let `\deg(x^a) = a_1 + a_2 + \dots + a_n`, then
     414`x^a < x^b` if and only if `\deg(x^a) < \deg(x^b)` or `\deg(x^a) = \deg(x^b)` and 
     415there exists `1 \le i \le n` such that `a_1 = b_1, \dots, a_{i-1} = b_{i-1}, a_i < b_i`.   
    337416"""
    338417
    339 rp_description = """
    340 Inverse lexicographic (invlex) term ordering.
     418neglex_description = """
     419Negative lexicographic (neglex) term order.
    341420
    342 $x^a < x^b \Leftrightarrow \exists\; 0 \le i < n : a_{n-1} = b_{n-1}, \ldots, a_{i+1} = b_{i+1}, a_i < b_i.$
     421`x^a < x^b` if and only if there exists `1 \le i \le n` such that `a_1 = b_1, \dots, a_{i-1} = b_{i-1}, a_i > b_i`.
    343422"""
    344423
    345 ls_description = """
    346 Negative lexicographic (neglex) term ordering.
     424negdegrevlex_description = """
     425Negative degree reverse lexicographic (negdegrevlex) term order.
    347426
    348 $x^a < x^b \Leftrightarrow \exists\; 0 \le i < n : a_0 = b_0, \ldots, a_{i-1} = b_{i-1}, a_i > b_i$
     427Let `\deg(x^a) = a_1 + a_2 + \dots + a_n`, then
     428`x^a < x^b` if and only if `\deg(x^a) > \deg(x^b)` or `\deg(x^a) = \deg(x^b)` and 
     429there exists `1 \le i \le n` such that `a_n = b_n, \dots, a_{i+1} = b_{i+1}, a_i > b_i`.   
     430"""   
     431
     432negdeglex_description = """
     433Negative degree lexicographic (negdeglex) term order.
     434
     435Let `\deg(x^a) = a_1 + a_2 + \dots + a_n`, then
     436`x^a < x^b` if and only if `\deg(x^a) > \deg(x^b)` or `\deg(x^a) = \deg(x^b)` and
     437there exists `1 \le i \le n` such that `a_1 = b_1, \dots, a_{i-1} = b_{i-1}, a_i < b_i`.
     438""" 
     439
     440wdegrevlex_description = """ 
     441Weighted degree reverse lexicographic (wdegrevlex) term order.
     442 
     443Let `\deg_w(x^a) = a_1w_1 + a_2w_2 + \dots + a_nw_n` with weights `w`, then
     444`x^a < x^b` if and only if `\deg_w(x^a) < \deg_w(x^b)` or `\deg_w(x^a) = \deg_w(x^b)` and 
     445there exists `1 \le i \le n` such that `a_n = b_n, \dots, a_{i+1} = b_{i+1}, a_i > b_i`.   
    349446"""
     447 
     448wdeglex_description = r""" 
     449Weighted degree lexicographic (wdeglex) term order.
    350450
    351 ds_description = """
    352 Negative degree reverse lexicographic (negdegrevlex) term ordering.
     451Let `\deg_w(x^a) = a_1w_1 + a_2w_2 + \dots + a_nw_n` with weights `w`, then
     452`x^a < x^b` if and only if `\deg_w(x^a) < \deg_w(x^b)` or `\deg_w(x^a) = \deg_w(x^b)` and
     453there exists `1 \le i \le n` such that `a_1 = b_1, \dots, a_{i-1} = b_{i-1}, a_i < b_i`. 
     454""" 
    353455
    354 Let $deg(x^a) = a_0 + \cdots + a_{n-1},$ then $x^a < x^b \Leftrightarrow deg(x^a) > deg(x^b)$ or
    355 $deg(x^a) = deg(x^b)$ and $\exists\ 0 \le i < n: a_{n-1} = b_{n-1}, \ldots, a_{i+1} = b_{i+1}, a_i > b_i.$
     456negwdegrevlex_description = """ 
     457Negative weighted degree reverse lexicographic (negwdegrevlex) term order.
     458
     459Let `\deg_w(x^a) = a_1w_1 + a_2w_2 + \dots + a_nw_n` with weights `w`, then
     460`x^a < x^b` if and only if `\deg_w(x^a) > \deg_w(x^b)` or `\deg_w(x^a) = \deg_w(x^b)` and 
     461there exists `1 \le i \le n` such that `a_n = b_n, \dots, a_{i+1} = b_{i+1}, a_i > b_i`. 
    356462"""
     463 
     464negwdeglex_description = """ 
     465Negative weighted degree lexicographic (negwdeglex) term order.
    357466
    358 Ds_description = """
    359 Negative degree lexicographic (negdeglex) term ordering.
     467Let `\deg_w(x^a) = a_1w_1 + a_2w_2 + \dots + a_nw_n` with weights `w`, then
     468`x^a < x^b` if and only if `\deg_w(x^a) > \deg_w(x^b)` or `\deg_w(x^a) = \deg_w(x^b)` and
     469there exists `1 \le i \le n` such that `a_1 = b_1, \dots, a_{i-1} = b_{i-1}, a_i < b_i`.   
     470"""   
    360471
    361 Let $deg(x^a) = a_0 + \cdots + a_{n-1},$ then $x^a < x^b \Leftrightarrow deg(x^a) > deg(x^b)$ or
    362 $deg(x^a) = deg(x^b)$ and $\exists\ 0 \le i < n: a_0 = b_0, \ldots, a_{i-1} = b_{i-1}, a_i < b_i.$
    363 """
     472matrix_description = """
     473Matrix term order defined by a matrix A.
     474
     475`x^a < x^b` if and only if `x^{Aa} < x^{Ab}` where `<` is the lexicographic term order.
     476""" 
     477
     478block_description = """
     479Block term order defined by term orders `<_1, <_2, \dots, <_n`.
     480
     481`x^a < x^b` if and only if `a = b` with respect to the first `n-1` term orders and `a <_n b`
     482with respect to the `n`th term order `<_n`.
     483"""   
    364484
    365485description_mapping = {
    366     "lp":lp_description,
    367     "dp":dp_description,
    368     "Dp":Dp_description,
    369     "rp":rp_description,
    370     "ls":ls_description,
    371     "Ds":Ds_description,
    372     "ds":ds_description}
     486    'lex'           : lex_description,
     487    'invlex'        : invlex_description,
     488    'degrevlex'     : degrevlex_description,
     489    'deglex'        : deglex_description,
     490    'neglex'        : neglex_description,
     491    'negdegrevlex'  : negdegrevlex_description,
     492    'negdeglex'     : negdeglex_description,
     493    'wdeglex'       : wdeglex_description,
     494    'wdegrevlex'    : wdegrevlex_description, 
     495    'negwdegrevlex' : negwdegrevlex_description,
     496    'negwdeglex'    : negwdeglex_description,
     497    'matrix'        : matrix_description,
     498    'block'         : block_description,
    373499
    374 M_description = """
    375 Matrix term ordering defined by a matrix A.
    376 
    377 $x^a < x^b \Leftrightarrow x^{Aa} <_{\mathrm{lex}} x^{Ab}$
    378 where $<_{\mathrm{lex}}$ is the lexicographic term ordering
    379 """ 
     500}
    380501
    381502class TermOrder(SageObject):
    382503    r"""
    383504    A term order.
    384505   
    385506    See ``sage.rings.polynomial.term_order`` for details
    386     on supported term orderings.
     507    on supported term orders.
    387508    """
    388     def __init__(self, name='lex', n = 0, blocks=True, force=False):
     509    def __setstate__(self, dict):
    389510        """
    390         Construct a new term ordering object.
     511        Translate pickled TermOrder objects with old data structure.
     512
     513        EXAMPLE::
     514
     515            sage: t = TermOrder('lex')
     516            sage: t2 = loads(dumps(t))
     517            sage: t2._weights is None
     518            True
     519        """
     520        if not dict.has_key('_weights'):
     521            name = dict['_TermOrder__name']
     522            n = dict['_TermOrder__length']
     523            t = TermOrder(name,n)
     524            self.__dict__.update(t.__dict__)
     525        else:             
     526            self.__dict__.update(dict)
     527
     528    def __init__(self, name='lex', n=0, blocks=True, force=False):
     529        """
     530        Construct a new term order object.
    391531       
    392532        INPUT:
    393533       
    394         - ``name`` - name of the term ordering (default: lex)
     534        - ``name`` - name of the term order (default: lex)
    395535       
    396         - ``n`` - number of variables in the polynomial ring
    397            (default: 0)
     536        - ``n`` - number of variables (default is `0`) or weights for
     537          weighted degree orders
     538
     539        - ``blocks`` - this is deprecated.
    398540       
    399         - ``blocks`` - controls whether a list of blocks is
    400            maintained (internal use only, default:True)
    401 
    402         - ``force`` - ignore unknown term orderings.
     541        - ``force`` - ignore unknown term orders.
    403542       
    404543        See the ``sage.rings.polynomial.term_order`` module
    405         for help which names and orderings are available.
     544        for help which names and orders are available.
    406545       
    407546        EXAMPLES::
    408547       
     
    412551            sage: loads(dumps(t)) == t
    413552            True
    414553       
    415         We can construct block orderings directly as
     554        We can construct block orders directly as
    416555       
    417556        ::
    418557       
    419558            sage: TermOrder('degrevlex(3),neglex(2)')
    420             degrevlex(3),neglex(2) term order
     559            Block term order with blocks:
     560            (Degree reverse lexicographic term order of length 3,
     561             Negative lexicographic term order of length 2)
    421562       
    422563        or by adding together the blocks::
    423564       
    424565            sage: t1 = TermOrder('degrevlex',3)
    425566            sage: t2 = TermOrder('neglex',2)
    426567            sage: t1 + t2
    427             degrevlex(3),neglex(2) term order
    428             sage: t2 + t1
    429             neglex(2),degrevlex(3) term order
     568            Block term order with blocks:
     569            (Degree reverse lexicographic term order of length 3,
     570             Negative lexicographic term order of length 2)
     571            sage: t3 = TermOrder('wdeglex',(1,2))
     572            sage: t1 + t3
     573            Block term order with blocks:
     574            (Degree reverse lexicographic term order of length 3,
     575             Weighted degree lexicographic term order with weights (1, 2))
    430576       
    431577        .. note::
    432578
    433579           The optional `n` parameter is not necessary if only
    434            non-block orderings like `deglex` are
    435            constructed. However, it is useful if block orderings are
     580           non-block orders like `deglex` are
     581           constructed. However, it is useful if block orders are
    436582           to be constructed from this ``TermOrder`` object later.
    437         """
     583        """ 
    438584        if isinstance(name, TermOrder):
    439             if n == 0 and len(name) > 0:
    440                 n = len(name)
     585            self.__copy(name)
     586            if n > 0 and not name.is_block_order() and not name.is_weighted_degree_order():
     587                self._length = n
     588            return 
     589
     590        if isinstance(name, str): 
     591            name = name.lower()
     592        else:
    441593            try:
    442                 force = name.__force
    443             except AttributeError: # pickled old TermOrders don't have this field
    444                 force = False
    445             name = name.name()
    446         else:
    447             try: # name is a matrix
    448                 name = 'M('+','.join(["%i"%(i,) for i in name.list()])+')'
     594                if not isinstance(name, (tuple,list)):
     595                    name = name.list() # name may be a matrix
     596                name = tuple(name)
    449597            except:
    450                 pass
    451         name = name.lower()
     598                raise TypeError, "%s is not a valid term order"%(name,)
    452599
    453         split_pattern = "([^(),]+(?:\([^()]*\)[^(),]*)*)" # split by outermost commas
    454         length_pattern  = re.compile("\(([0-9]+)\)$") # match with parenthesized block length at end
    455         matrix_pattern = "([0-9,]+)" # match with list of integers
    456        
    457         self.__force = force
    458         self.__length = 0
    459         self.__name = ""
    460         self.__singular_str = ""
    461         self.__macaulay2_str = ""
    462         self.__magma_str = ""
    463         self.__matrix = None # only for matrix ordering
    464          
    465         block_names = re.findall(split_pattern,name)
     600        self._blocks = tuple()
     601        self._weights = None
     602        self._matrix = None
    466603
    467         if len(block_names) == 0:
    468             raise TypeError, "No term ordering specified"
    469         elif len(block_names) == 1:
    470             name = block_names[0]
    471             if re.match('m\(([0-9,]+)\)$',name) != None: # matrix ordering
    472                 integers_str = re.search(matrix_pattern,name).group()
    473                 integers = map(int,integers_str.split(','))
    474 
    475                 if n == 0:
    476                     from math import sqrt
    477                     n = int(sqrt(len(integers)))
    478 
    479                 if len(integers) != n**2:
    480                     raise TypeError, "%s does not specify a square matrix"%(name,)
    481 
    482                 self.__matrix = []
    483                 for idx in range(0,len(integers),n):
    484                     self.__matrix.append(integers[idx:idx+n])
    485 
    486                 self.__length = n
    487                 self.__name = "M(%s)"%(integers_str,)
    488                 self.__singular_str = "M(%s)"%(integers_str,)
    489                 self.__macaulay2_str = "" # Macaulay2 does not support matrix term order directly
    490                 self.__magma_str = '"weight",[%s]'%(integers_str,)
    491                 self.__doc__ = M_description
    492 
    493             else: # simple ordering
    494                 self.__length = n
    495                 self.__name = name
    496                 self.__singular_str = singular_name_mapping.get(name,name)
    497                 self.__macaulay2_str = macaulay2_name_mapping.get(name,name)
    498                 self.__magma_str = magma_name_mapping.get(name,name)
    499 
    500                 if self.__singular_str in description_mapping:
    501                     self.__doc__ = description_mapping[self.__singular_str]                 
    502            
    503             from sage.misc.misc import verbose
    504             if blocks:
    505                 # we allow deglex_asc here which is used by PolyBoRi
    506                 if self.__matrix == None and \
    507                    name not in singular_name_mapping.keys() and \
    508                    name not in singular_name_mapping.values() and not force:
    509                     verbose("Term ordering '%s' unknown."%name,level=0)
    510                 self.blocks = (TermOrder(self.__name,n,blocks=False,force=force),)
    511             else:
    512                 self.blocks = tuple()   
    513 
    514         else: # block ordering
     604        if name == "block": # block term order with blocks in a list
    515605            length = 0
    516606            blocks = []
    517607            name_str = []
    518608            singular_str = []
    519609            macaulay2_str = []
    520610
    521             for block in block_names:
    522                 try:
    523                     block_name, block_length, _ = re.split(length_pattern,block)
    524                 except ValueError:
    525                     raise TypeError, "%s is not a valid term ordering"%(name,)
     611            for t in n:
     612                if not isinstance(t, TermOrder):
     613                    try:
     614                        t = TermOrder(t,force=True)
     615                    except:
     616                        raise TypeError
     617                if t.name() == 'block':
     618                    blocks = blocks + list(t.blocks())
     619                    singular_str.append("%s"%(t.singular_str()[1:-1],))  # [1:-1] is needed to remove parenthesis
     620                    macaulay2_str.append("%s"%(t.macaulay2_str()[1:-1],)) 
     621                else:
     622                    if len(t) == 0:
     623                        raise ArithmeticError, "Can only concatenate term orders with length attribute."   
     624                    blocks.append(t)
     625                    if t.is_weighted_degree_order(): # true if t is a matrix order as well
     626                        singular_str.append("%s"%(t.singular_str(),))
     627                    else:
     628                        singular_str.append("%s(%d)"%(t.singular_str(), len(t)))                                           
     629                    macaulay2_str.append("%s => %d"%(t.macaulay2_str(), len(t)))
     630                length += len(t)
    526631
    527                 block_length = int(block_length)
     632            self._length = length
     633            self._name = "block"
     634            self._singular_str = "(" + ",".join(singular_str) + ")"
     635            self._macaulay2_str = "{" + ",".join(macaulay2_str) + "}"
     636            self._magma_str = "" # Magma does not support block order
     637            self._blocks = tuple(blocks)
     638        elif isinstance(name, str) and not (isinstance(n, tuple) or isinstance(n,list)): # string representation of simple or block orders
     639            split_pattern = "([^(),]+(?:\([^()]*\)[^(),]*)*)" # split by outermost commas         
     640            block_names = re.findall(split_pattern,name)
    528641
    529                 blocks.append( TermOrder(block_name,block_length,force=force) )
    530                 name_str.append("%s(%d)"%(block_name,block_length))
    531                 singular_str.append("%s(%d)"%(singular_name_mapping.get(block_name, block_name), block_length))
    532                 macaulay2_str.append("%s => %d"%(macaulay2_name_mapping.get(block_name, block_name), block_length))
     642            if len(block_names) == 0:
     643                raise TypeError, "No term order specified"
     644            elif len(block_names) == 1:
     645                name = block_names[0]
     646                match = re.match('m\(([-+0-9,]+)\)$',name)
     647                if match: # matrix term order
     648                    m = map(int,match.groups()[0].split(',')) # replace match.groups()[0]  with match.group(1) later
     649                    self.__copy(TermOrder(m))
     650                else: # simple order
     651                    if name not in print_name_mapping.keys() and name not in singular_name_mapping.values() and not force:
     652                        raise TypeError, "Unknown term order '%s'"%(name,)
     653                    self._length = n
     654                    self._name = name
     655                    self._singular_str = singular_name_mapping.get(name,name)
     656                    self._macaulay2_str = macaulay2_name_mapping.get(name,name)
     657                    self._magma_str = magma_name_mapping.get(name,name)               
     658            else: # len(block_names) > 1, and hence block order represented by a string
     659                length = 0
     660                blocks = []
     661                name_str = []
     662                singular_str = []
     663                macaulay2_str = []
    533664
    534                 length += block_length
     665                for block in block_names:
     666                    try:
     667                        length_pattern  = re.compile("\(([0-9]+)\)$") # match with parenthesized block length at end                 
     668                        block_name, block_length, _ = re.split(length_pattern,block)
     669                        block_length = int(block_length)
     670                        blocks.append( TermOrder(block_name,block_length,force=force) )
     671                    except:
     672                        raise TypeError, "%s is not a valid term order"%(name,)
     673                    length += block_length
    535674
    536             self.blocks = tuple(blocks)
    537             self.__length = length
    538             self.__name = ",".join(name_str)
    539             self.__singular_str = "(" + ",".join(singular_str) + ")"
    540             self.__macaulay2_str = "(" + ",".join(macaulay2_str) + ")"
    541             self.__magma_str = "" # Magma does not support block order
     675                if n != 0 and length != n:
     676                    raise TypeError, "Term order length does not match the number of generators"
     677                self.__copy(TermOrder('block', blocks))
     678        elif isinstance(name, str) and (isinstance(n, tuple) or isinstance(n,list)): # weighted degree term orders
     679            if name not in print_name_mapping.keys() and name not in singular_name_mapping.values() and not force:
     680                raise TypeError, "Unknown term order '%s'"%(name,) 
     681            weights = tuple(n) # n is a tuple of weights
     682           
     683            self._length = len(weights)
     684            self._name = name
     685            self._singular_str = singular_name_mapping.get(name,name) + '(' + ','.join([str(w) for w in weights]) + ')'
     686            self._macaulay2_str = ""
     687            self._magma_str = ""
     688            self._weights = weights # defined only for weighted degree orders                   
     689        elif isinstance(name, tuple): # name represents a matrix 
     690            if n == 0:
     691                from math import sqrt
     692                n = int(sqrt(len(name)))                   
     693            if n**2 != len(name):
     694                raise TypeError, "%s does not specify a square matrix"%(name,)   
    542695
    543             if n != 0 and self.__length != n:
    544                 raise TypeError, "Term order length does not match the number of generators"
     696            int_str = ','.join([str(int(e)) for e in name])
     697
     698            self._length = n
     699            self._name = "matrix"
     700            self._singular_str = "M(%s)"%(int_str,)
     701            self._macaulay2_str = "" # Macaulay2 does not support matrix term order directly
     702            self._magma_str = '"weight",[%s]'%(int_str,)
     703
     704            from sage.matrix.constructor import matrix   
     705            self._matrix = matrix(n,name)  # defined only for matrix term order
     706            self._weights = name[:n] # the first row of the matrix gives weights
     707        else:
     708            raise TypeError, "%s is not a valid term order"%(name,)   
     709
     710        self.__doc__ = description_mapping.get(self._name, "No description available")                 
     711
     712    def __copy(self, other):
     713        """
     714        Copy other term order to self.
     715
     716        EXAMPLE::
     717       
     718            sage: t = TermOrder('lex')
     719            sage: s = TermOrder(t)
     720            sage: t == s            # indirect test
     721            True
     722        """
     723        self.__dict__ = other.__dict__.copy()
    545724
    546725    def __getattr__(self,name):
    547726        """
     
    550729        EXAMPLE::
    551730       
    552731            sage: TermOrder('lex').compare_tuples
    553             <bound method TermOrder.compare_tuples_lp of Lexicographic term order>
     732            <bound method TermOrder.compare_tuples_lex of Lexicographic term order>
    554733       
    555734        ::
    556735       
    557736            sage: TermOrder('deglex').compare_tuples
    558             <bound method TermOrder.compare_tuples_Dp of Degree lexicographic term order>
     737            <bound method TermOrder.compare_tuples_deglex of Degree lexicographic term order>
    559738        """
    560739        if name == 'compare_tuples':
    561             if len(self.blocks) <= 1:
    562                 if self.__matrix != None:
    563                     return self.compare_tuples_matrix
    564                 else:
    565                     return getattr(self,'compare_tuples_'+self.__singular_str)
    566             else:
    567                 return self.compare_tuples_block
     740            return getattr(self,'compare_tuples_'+self._name)
    568741        elif name == 'greater_tuple':
    569             if len(self.blocks) <= 1:
    570                 if self.__matrix != None:
    571                     return self.greater_tuple_matrix
    572                 else:
    573                     return getattr(self,'greater_tuple_'+self.__singular_str)
    574             else:
    575                 return self.greater_tuple_block
     742            return getattr(self,'greater_tuple_'+self._name)
    576743        else:
    577744            raise AttributeError,name
    578745
     
    595762            sage: y > x^3
    596763            False
    597764        """
    598         for row in self.__matrix:
    599             mf = sum(l*r for (l,r) in zip(row,f))
    600             mg = sum(l*r for (l,r) in zip(row,g))
     765        for row in self._matrix:
     766            sf = sum(l*r for (l,r) in zip(row,f))
     767            sg = sum(l*r for (l,r) in zip(row,g))
    601768       
    602             if mf > mg:
     769            if sf > sg:
    603770                return 1
    604             elif mf < mg:
     771            elif sf < sg:
    605772                return -1
    606773        return 0 
    607774
    608     def compare_tuples_lp(self,f,g):
     775    def compare_tuples_lex(self,f,g):
    609776        """
    610777        Compares two exponent tuples with respect to the lexicographical
    611778        term order.
     
    624791            sage: x > 1
    625792            True
    626793        """
    627 
    628         if f>g:
     794        if f > g:
    629795            return 1
    630         elif f<g:
     796        elif f < g:
    631797            return -1
    632798        else:
    633799            return 0
    634800
    635     def compare_tuples_rp(self,f,g):
     801    def compare_tuples_invlex(self,f,g):
    636802        """
    637803        Compares two exponent tuples with respect to the inversed
    638804        lexicographical term order.
     
    651817            sage: x > 1
    652818            True
    653819        """
    654         return self.compare_tuples_lp(f.reversed(),g.reversed())
     820        return self.compare_tuples_lex(f.reversed(),g.reversed())
    655821
    656     def compare_tuples_Dp(self,f,g):
     822    def compare_tuples_deglex(self,f,g):
    657823        """
    658824        Compares two exponent tuples with respect to the degree
    659825        lexicographical term order.
     
    676842        sg = sum(g.nonzero_values(sort=False))
    677843        if sf > sg:
    678844            return 1
    679         elif sf<sg:
     845        elif sf < sg:
    680846            return -1
    681847        elif sf == sg:
    682             return self.compare_tuples_lp(f,g)
     848            return self.compare_tuples_lex(f,g)
    683849
    684     def compare_tuples_dp(self,f,g):
     850    def compare_tuples_degrevlex(self,f,g):
    685851        """
    686852        Compares two exponent tuples with respect to the degree reversed
    687853        lexicographical term order.
     
    704870        sg = sum(g.nonzero_values(sort=False))
    705871        if sf > sg:
    706872            return 1
    707         elif sf<sg:
     873        elif sf < sg:
    708874            return -1
    709875        elif sf == sg:
    710             return (-1)*self.compare_tuples_lp(f.reversed(),g.reversed())
     876            return -self.compare_tuples_lex(f.reversed(),g.reversed())
    711877
    712     def compare_tuples_ls(self,f,g):
     878    def compare_tuples_neglex(self,f,g):
    713879        """
    714880        Compares two exponent tuples with respect to the negative
    715881        lexicographical term order.
     
    728894            sage: x > 1
    729895            False
    730896        """
    731         return -self.compare_tuples_lp(f,g)
     897        return -self.compare_tuples_lex(f,g)
    732898
    733     def compare_tuples_ds(self,f,g):
     899    def compare_tuples_negdegrevlex(self,f,g):
    734900        """
    735901        Compares two exponent tuples with respect to the negative degree
    736902        reverse lexicographical term order.
     
    753919        sg = sum(g.nonzero_values(sort=False))
    754920        if sf > sg:
    755921            return -1
    756         elif sf<sg:
     922        elif sf < sg:
    757923            return 1
    758924        elif sf == sg:
    759             return (-1)*self.compare_tuples_lp(f.reversed(),g.reversed())
     925            return (-1)*self.compare_tuples_lex(f.reversed(),g.reversed())
    760926
    761     def compare_tuples_Ds(self,f,g):
     927    def compare_tuples_negdeglex(self,f,g):
    762928        """
    763929        Compares two exponent tuples with respect to the negative degree
    764930        lexicographical term order.
     
    781947        sg = sum(g.nonzero_values(sort=False))
    782948        if sf > sg:
    783949            return -1
    784         elif sf<sg:
     950        elif sf < sg:
    785951            return 1
    786952        elif sf == sg:
    787             return self.compare_tuples_lp(f,g)
     953            return self.compare_tuples_lex(f,g)
     954
     955    def compare_tuples_wdegrevlex(self,f,g):
     956        """
     957        Compares two exponent tuples with respect to the weighted degree reverse
     958        lexicographical term order.
     959       
     960        INPUT:
     961       
     962        - ``f`` - exponent tuple
     963       
     964        - ``g`` - exponent tuple
     965       
     966        EXAMPLE::
     967 
     968            sage: t = TermOrder('wdegrevlex',(3,2)) 
     969            sage: P.<x,y> = PolynomialRing(QQbar, 2, order=t)
     970            sage: x > y^2 # indirect doctest
     971            False
     972            sage: x^2 > y^3
     973            True
     974        """
     975        sf = sum(l*r for (l,r) in zip(f,self._weights))
     976        sg = sum(l*r for (l,r) in zip(g,self._weights)) 
     977        if sf > sg:
     978            return 1
     979        elif sf < sg:
     980            return -1
     981        elif sf == sg:
     982            return -self.compare_tuples_lex(f.reversed(),g.reversed()) 
     983
     984    def compare_tuples_wdeglex(self,f,g):
     985        """
     986        Compares two exponent tuples with respect to the weighted degree
     987        lexicographical term order.
     988       
     989        INPUT:
     990       
     991        - ``f`` - exponent tuple
     992       
     993        - ``g`` - exponent tuple
     994       
     995        EXAMPLE::
     996       
     997            sage: t = TermOrder('wdeglex',(3,2))
     998            sage: P.<x,y> = PolynomialRing(QQbar, 2, order=t)
     999            sage: x > y^2 # indirect doctest
     1000            False
     1001            sage: x > y
     1002            True
     1003        """
     1004        sf = sum(l*r for (l,r) in zip(f,self._weights))
     1005        sg = sum(l*r for (l,r) in zip(g,self._weights)) 
     1006        if sf > sg:
     1007            return 1
     1008        elif sf < sg:
     1009            return -1
     1010        elif sf == sg:
     1011            return self.compare_tuples_lex(f,g)   
     1012
     1013    def compare_tuples_negwdeglex(self,f,g):
     1014        """
     1015        Compares two exponent tuples with respect to the negative weighted
     1016        degree lexicographical term order.
     1017       
     1018        INPUT:
     1019       
     1020        - ``f`` - exponent tuple
     1021       
     1022        - ``g`` - exponent tuple
     1023       
     1024        EXAMPLE::
     1025
     1026            sage: t = TermOrder('negwdeglex',(3,2)) 
     1027            sage: P.<x,y> = PolynomialRing(QQbar, 2, order=t)
     1028            sage: x > y^2 # indirect doctest
     1029            True
     1030            sage: x^2 > y^3
     1031            True
     1032        """
     1033        sf = sum(l*r for (l,r) in zip(f,self._weights))
     1034        sg = sum(l*r for (l,r) in zip(g,self._weights)) 
     1035        if sf > sg:
     1036            return -1
     1037        elif sf < sg:
     1038            return 1
     1039        elif sf == sg:
     1040            return self.compare_tuples_lex(f,g) 
     1041 
     1042    def compare_tuples_negwdegrevlex(self,f,g):
     1043        """
     1044        Compares two exponent tuples with respect to the negative weighted
     1045        degree reverse lexicographical term order.
     1046       
     1047        INPUT:
     1048       
     1049        - ``f`` - exponent tuple
     1050       
     1051        - ``g`` - exponent tuple
     1052       
     1053        EXAMPLE::
     1054 
     1055             sage: t = TermOrder('negwdegrevlex',(3,2))   
     1056            sage: P.<x,y> = PolynomialRing(QQbar, 2, order=t)
     1057            sage: x > y^2 # indirect doctest
     1058            True
     1059            sage: x^2 > y^3
     1060            True
     1061        """
     1062        sf = sum(l*r for (l,r) in zip(f,self._weights))
     1063        sg = sum(l*r for (l,r) in zip(g,self._weights))   
     1064        if sf > sg:
     1065            return -1
     1066        elif sf < sg:
     1067            return 1
     1068        elif sf == sg:
     1069            return (-1)*self.compare_tuples_lex(f.reversed(),g.reversed())
    7881070
    7891071    def compare_tuples_block(self, f,g):
    7901072        """
    791         Compares two exponent tuples with respect to the block ordering as
     1073        Compares two exponent tuples with respect to the block order as
    7921074        specified when constructing this element.
    7931075       
    7941076        INPUT:
     
    8061088            True
    8071089        """
    8081090        n = 0
    809         for order in self:
    810             r = getattr(self,"compare_tuples_"+order.singular_str())(f[n:n+len(order)],g[n:n+len(order)])
     1091        for block in self:
     1092            r = getattr(block,"compare_tuples_" + block.name())(f[n:n+len(block)],g[n:n+len(block)])
    8111093            if r != 0:
    8121094                return r
    813             n += len(order)
     1095            n += len(block)
    8141096        return 0
    8151097
    8161098    def greater_tuple_matrix(self,f,g):
     
    8321114            sage: y > x^3
    8331115            False
    8341116        """
    835         for row in self.__matrix:
    836             mf = sum(l*r for (l,r) in zip(row,f))
    837             mg = sum(l*r for (l,r) in zip(row,g))
     1117        for row in self._matrix:
     1118            sf = sum(l*r for (l,r) in zip(row,f))
     1119            sg = sum(l*r for (l,r) in zip(row,g))
    8381120       
    839             if mf>mg:
     1121            if sf > sg:
    8401122                return f
    841             elif mf<mg:
     1123            elif sf < sg:
    8421124                return g
    8431125        return g   
    8441126
    845     def greater_tuple_lp(self,f,g):
     1127    def greater_tuple_lex(self,f,g):
    8461128        """
    847         Returns the greater exponent tuple with respect to the
     1129        Return the greater exponent tuple with respect to the
    8481130        lexicographical term order.
    8491131       
    8501132        INPUT:
     
    8641146        """
    8651147        return f > g and f or g
    8661148
    867     def greater_tuple_rp(self,f,g):
     1149    def greater_tuple_invlex(self,f,g):
    8681150        """
    869         Returns the greater exponent tuple with respect to the inversed
     1151        Return the greater exponent tuple with respect to the inversed
    8701152        lexicographical term order.
    8711153       
    8721154        INPUT:
     
    8861168        This method is called by the lm/lc/lt methods of
    8871169        ``MPolynomial_polydict``.
    8881170        """
    889         return f.reversed() > g.reversed()   and f or g
     1171        return f.reversed() > g.reversed() and f or g
    8901172       
    891     def greater_tuple_Dp(self,f,g):
     1173    def greater_tuple_deglex(self,f,g):
    8921174        """
    893         Returns the greater exponent tuple with respect to the total degree
     1175        Return the greater exponent tuple with respect to the total degree
    8941176        lexicographical term order.
    8951177       
    8961178        INPUT:
     
    9101192        This method is called by the lm/lc/lt methods of
    9111193        ``MPolynomial_polydict``.
    9121194        """
    913         return (sum(f.nonzero_values(sort=False))>sum(g.nonzero_values(sort=False))
    914                 or (sum(f.nonzero_values(sort=False))==sum(g.nonzero_values(sort=False)) and f  > g )) and f or g
     1195        sf = sum(f.nonzero_values(sort=False))
     1196        sg = sum(g.nonzero_values(sort=False))
     1197        return ( sf > sg or ( sf == sg and f  > g )) and f or g
    9151198   
    916     def greater_tuple_dp(self,f,g):
     1199    def greater_tuple_degrevlex(self,f,g):
    9171200        """
    918         Returns the greater exponent tuple with respect to the total degree
     1201        Return the greater exponent tuple with respect to the total degree
    9191202        reversed lexicographical term order.
    9201203       
    9211204        INPUT:
     
    9351218        This method is called by the lm/lc/lt methods of
    9361219        ``MPolynomial_polydict``.
    9371220        """
    938         return (sum(f.nonzero_values(sort=False))>sum(g.nonzero_values(sort=False))
    939                 or (sum(f.nonzero_values(sort=False))==sum(g.nonzero_values(sort=False))
    940                     and f.reversed() < g.reversed())) and f or g
     1221        sf = sum(f.nonzero_values(sort=False))
     1222        sg = sum(g.nonzero_values(sort=False))
     1223        return ( sf > sg or ( sf == sg and f.reversed() < g.reversed() )) and f or g         
    9411224   
    942     def greater_tuple_ds(self,f,g):
     1225    def greater_tuple_negdegrevlex(self,f,g):
    9431226        """
    944         Returns the greater exponent tuple with respect to the negative
     1227        Return the greater exponent tuple with respect to the negative
    9451228        degree reverse lexicographical term order.
    9461229       
    9471230        INPUT:
     
    9631246        This method is called by the lm/lc/lt methods of
    9641247        ``MPolynomial_polydict``.
    9651248        """
    966         if self.compare_tuples_ds(f,g) >= 0:
    967             return f
    968         else:
    969             return g
     1249        sf = sum(f.nonzero_values(sort=False))
     1250        sg = sum(g.nonzero_values(sort=False))
     1251        return ( sf < sg or ( sf == sg and f.reversed() < g.reversed() )) and f or g
    9701252
    971     def greater_tuple_Ds(self,f,g):
     1253    def greater_tuple_negdeglex(self,f,g):
    9721254        """
    973         Returns the greater exponent tuple with respect to the negative
     1255        Return the greater exponent tuple with respect to the negative
    9741256        degree lexicographical term order.
    9751257       
    9761258        INPUT:
     
    9921274        This method is called by the lm/lc/lt methods of
    9931275        ``MPolynomial_polydict``.
    9941276        """
    995         if self.compare_tuples_Ds(f,g) >= 0:
    996             return f
    997         else:
    998             return g
     1277        sf = sum(f.nonzero_values(sort=False))
     1278        sg = sum(g.nonzero_values(sort=False))
     1279        return ( sf < sg or ( sf == sg and f  > g )) and f or g   
    9991280
    1000     def greater_tuple_ls(self,f,g):
     1281    def greater_tuple_neglex(self,f,g):
    10011282        """
    1002         Returns the greater exponent tuple with respect to the negative
     1283        Return the greater exponent tuple with respect to the negative
    10031284        lexicographical term order.
    10041285       
    10051286        This method is called by the lm/lc/lt methods of
     
    10191300            sage: g = a + e^4; g.lm()
    10201301            a
    10211302        """
    1022         if self.greater_tuple_lp(f,g) is f:
    1023             return g
    1024         else:
    1025             return f
     1303        return (f < g) and f or g
    10261304
     1305    def greater_tuple_wdeglex(self,f,g):
     1306        """
     1307        Return the greater exponent tuple with respect to the weighted degree
     1308        lexicographical term order.
     1309       
     1310        INPUT:
     1311       
     1312        - ``f`` - exponent tuple
     1313       
     1314        - ``g`` - exponent tuple
     1315       
     1316        EXAMPLE::
     1317
     1318            sage: t = TermOrder('wdeglex',(1,2,3))
     1319            sage: P.<x,y,z> = PolynomialRing(QQbar, 3, order=t)
     1320            sage: f = x + y; f.lm() # indirect doctest
     1321            y
     1322            sage: f = x*y + z; f.lm()
     1323            x*y
     1324       
     1325        This method is called by the lm/lc/lt methods of
     1326        ``MPolynomial_polydict``.
     1327        """
     1328        sf = sum(l*r for (l,r) in zip(f,self._weights))
     1329        sg = sum(l*r for (l,r) in zip(g,self._weights))         
     1330        return (sf > sg or ( sf == sg and f  > g )) and f or g   
     1331 
     1332    def greater_tuple_wdegrevlex(self,f,g):
     1333        """
     1334        Return the greater exponent tuple with respect to the weighted degree
     1335        reverse lexicographical term order.
     1336       
     1337        INPUT:
     1338       
     1339        - ``f`` - exponent tuple
     1340       
     1341        - ``g`` - exponent tuple
     1342       
     1343        EXAMPLES::
     1344       
     1345            sage: t = TermOrder('wdegrevlex',(1,2,3))
     1346            sage: P.<x,y,z> = PolynomialRing(QQbar, 3, order=t)
     1347            sage: f = x + y; f.lm() # indirect doctest
     1348            y
     1349            sage: f = x + y^2*z; f.lm()
     1350            y^2*z
     1351       
     1352        This method is called by the lm/lc/lt methods of
     1353        ``MPolynomial_polydict``.
     1354        """
     1355        sf = sum(l*r for (l,r) in zip(f,self._weights))
     1356        sg = sum(l*r for (l,r) in zip(g,self._weights))         
     1357        return (sf > sg or ( sf == sg and f.reversed() < g.reversed())) and f or g 
     1358
     1359    def greater_tuple_negwdeglex(self,f,g):
     1360        """
     1361        Return the greater exponent tuple with respect to the negative
     1362        weighted degree lexicographical term order.
     1363       
     1364        INPUT:
     1365       
     1366        - ``f`` - exponent tuple
     1367       
     1368        - ``g`` - exponent tuple
     1369       
     1370        EXAMPLE::
     1371       
     1372            sage: t = TermOrder('negwdeglex',(1,2,3))
     1373            sage: P.<x,y,z> = PolynomialRing(QQbar, 3, order=t) 
     1374            sage: f = x + y; f.lm() # indirect doctest
     1375            x
     1376            sage: f = x + x^2; f.lm()
     1377            x
     1378            sage: f = x^3 + z; f.lm()
     1379            x^3
     1380       
     1381        This method is called by the lm/lc/lt methods of
     1382        ``MPolynomial_polydict``.
     1383        """
     1384        sf = sum(l*r for (l,r) in zip(f,self._weights))
     1385        sg = sum(l*r for (l,r) in zip(g,self._weights)) 
     1386        return (sf < sg or ( sf == sg and f  > g )) and f or g 
     1387
     1388    def greater_tuple_negwdegrevlex(self,f,g):
     1389        """
     1390        Return the greater exponent tuple with respect to the negative
     1391        weighted degree reverse lexicographical term order.
     1392       
     1393        INPUT:
     1394       
     1395        - ``f`` - exponent tuple
     1396       
     1397        - ``g`` - exponent tuple
     1398       
     1399        EXAMPLE::
     1400       
     1401            sage: t = TermOrder('negwdegrevlex',(1,2,3))
     1402            sage: P.<x,y,z> = PolynomialRing(QQbar, 3, order=t)
     1403            sage: f = x + y; f.lm() # indirect doctest
     1404            x
     1405            sage: f = x + x^2; f.lm()
     1406            x
     1407            sage: f = x^3 + z; f.lm() 
     1408            x^3
     1409       
     1410        This method is called by the lm/lc/lt methods of
     1411        ``MPolynomial_polydict``.
     1412        """
     1413        sf = sum(l*r for (l,r) in zip(f,self._weights))
     1414        sg = sum(l*r for (l,r) in zip(g,self._weights)) 
     1415        return (sf < sg or ( sf == sg and f.reversed() < g.reversed() )) and f or g   
     1416       
    10271417    def greater_tuple_block(self, f,g):
    10281418        """
    1029         Returns the greater exponent tuple with respect to the block
    1030         ordering as specified when constructing this element.
     1419        Return the greater exponent tuple with respect to the block
     1420        order as specified when constructing this element.
    10311421       
    10321422        This method is called by the lm/lc/lt methods of
    10331423        ``MPolynomial_polydict``.
     
    10471437            a
    10481438        """
    10491439        n = 0
    1050         for order in self:
    1051             r = getattr(self,"compare_tuples_"+order.singular_str())(f[n:n+len(order)],g[n:n+len(order)])
     1440        for block in self:
     1441            r = getattr(block,"compare_tuples_" + block.name())(f[n:n+len(block)],g[n:n+len(block)])
    10521442            if r != 0:
    10531443                if r < 0:
    10541444                    return g
    10551445                else:
    10561446                    return f
    1057             n += len(order)
     1447            n += len(block)
    10581448        return f
    10591449
     1450    def tuple_weight(self, f):
     1451        """
     1452        Return the weight of tuple f.
     1453
     1454        INPUT:
     1455       
     1456        - ``f`` - exponent tuple 
     1457
     1458        EXAMPLE::   
     1459
     1460            sage: t=TermOrder('wdeglex',(1,2,3))
     1461            sage: P.<a,b,c>=PolynomialRing(QQbar, order=t)
     1462            sage: P.term_order().tuple_weight([3,2,1])
     1463            10
     1464        """
     1465        return sum(l*r for (l,r) in zip(f,self._weights))
     1466
    10601467    def name(self):
    10611468        """
    10621469        EXAMPLE::
     
    10641471            sage: TermOrder('lex').name()
    10651472            'lex'
    10661473        """
    1067         return self.__name
     1474        return self._name
    10681475
    10691476    def _repr_(self):
    10701477        """
     
    10731480            sage: TermOrder('lex') # indirect doctest
    10741481            Lexicographic term order
    10751482        """
    1076         if self.__name[0] == 'M':
    1077             return 'Matrix term order with matrix\n%s'%self.matrix()
     1483        if self._name == 'matrix':
     1484            return 'Matrix term order with matrix\n%s'%(self._matrix,)
     1485        elif self._name == 'block':
     1486            s = []
     1487            for t in self._blocks:
     1488                if not t.is_weighted_degree_order():
     1489                    s.append('%s of length %d'%(t,len(t)))
     1490                else: # includes matrix order
     1491                    s.append('%s'%(t,))
     1492            return 'Block term order with blocks:\n(%s)'%(',\n '.join(s),)
    10781493        else:
    1079             s = print_name_mapping.get(self.__name,self.__name)
    1080             return '%s term order'%s
     1494            s = print_name_mapping.get(self._name,self._name) + ' term order'
     1495            if self.is_weighted_degree_order():
     1496                s = s + ' with weights %s'%(self._weights,)
     1497            return s
    10811498
    10821499    def singular_str(self):
    10831500        """
     
    11021519            //                  : names    x8 x9
    11031520            //        block   4 : ordering C
    11041521        """
    1105         return self.__singular_str
     1522        return self._singular_str
    11061523
    11071524    def macaulay2_str(self):
    11081525        """
     
    11161533            sage: P = PolynomialRing(GF(127), 8,names='x',order='degrevlex(3),lex(5)')
    11171534            sage: T = P.term_order()
    11181535            sage: T.macaulay2_str()
    1119             '(GRevLex => 3,Lex => 5)'
     1536            '{GRevLex => 3,Lex => 5}'
    11201537            sage: P._macaulay2_() # optional - macaulay2
    11211538            ZZ/127 [x0, x1, x2, x3, x4, x5, x6, x7, MonomialOrder => {GRevLex => 3, Lex => 5}, MonomialSize => 16]
    11221539        """
    1123         return self.__macaulay2_str
     1540        return self._macaulay2_str
    11241541
    11251542    def magma_str(self):
    11261543        """
     
    11421559            sage: T.magma_str()
    11431560            '"grevlex"'
    11441561        """
    1145         return self.__magma_str
     1562        return self._magma_str
     1563
     1564    def blocks(self):
     1565        """
     1566        Return the term order blocks of self.
     1567
     1568        EXAMPLE::
     1569
     1570            sage: t=TermOrder('deglex',2)+TermOrder('lex',2)
     1571            sage: t.blocks()
     1572            (Degree lexicographic term order, Lexicographic term order)
     1573        """
     1574        if self._blocks: # self is a block order
     1575            return self._blocks
     1576        else:
     1577            return [self]
    11461578
    11471579    def matrix(self):   
    11481580        """
    1149         Return the matrix defining matrix ordering.
     1581        Return the matrix defining matrix term order.
    11501582
    11511583        EXAMPLE::
    11521584
     
    11561588            [0 1]
    11571589           
    11581590        """
    1159         from sage.matrix.constructor import matrix
    1160         return matrix(self.__matrix)
     1591        return self._matrix
    11611592
    1162     def __cmp__(self, other):
     1593    def weights(self):
    11631594        """
    1164         Only equality testing makes sense here.
    1165        
     1595        Return the weights for weighted term orders.
     1596
     1597        EXAMPLE::
     1598
     1599            sage: t=TermOrder('wdeglex',(2,3))
     1600            sage: t.weights()
     1601            (2, 3)
     1602        """           
     1603        return self._weights
     1604
     1605    def __eq__(self, other):
     1606        """
     1607        Return true if self and other are equal.
     1608
    11661609        EXAMPLE::
    11671610       
    11681611            sage: TermOrder('lex') == TermOrder('lex',3)
     
    11781621            sage: T1 = TermOrder('lex',2)+TermOrder('lex',3)
    11791622            sage: T2 = TermOrder('lex',3)+TermOrder('lex',2)
    11801623            sage: T1 == T2
    1181             False
     1624            True
    11821625       
    11831626        ::
    11841627       
     
    11881631            True
    11891632        """
    11901633        if not isinstance(other, TermOrder):
    1191             if isinstance(other, str):
     1634            try:
    11921635                other = TermOrder(other, force=True)
    1193             else:
    1194                 return cmp(type(self), type(other))
    1195         return cmp(self.singular_str(), other.singular_str())
     1636            except:
     1637                return False
     1638
     1639        return (self._name == other._name       # note that length is not considered.
     1640            and self._blocks == other._blocks
     1641            and self._weights == other._weights
     1642            and self._matrix == other._matrix)
     1643
     1644    def __ne__(self, other):
     1645        """
     1646        Return true if self and other are not equal.
     1647
     1648        EXAMPLE::
     1649       
     1650            sage: T1 = TermOrder('lex',2)+TermOrder('lex',3)
     1651            sage: T2 = TermOrder('lex',3)+TermOrder('lex',2)
     1652            sage: T1 != T2
     1653            False 
     1654        """
     1655        return not self.__eq__(other)
    11961656
    11971657    def __add__(self, other):
    11981658        """
    1199         Block ordering constructor.
     1659        Construct a block order combining self and other.
    12001660       
    12011661        INPUT:
    12021662       
    12031663        - ``other`` - a term order
    12041664       
    1205         OUTPUT: a block ordering
     1665        OUTPUT: a block order
    12061666       
    12071667        EXAMPLE::
    12081668       
    12091669            sage: from sage.rings.polynomial.term_order import TermOrder
    12101670            sage: TermOrder('deglex',2) + TermOrder('degrevlex(3),neglex(3)')
    1211             deglex(2),degrevlex(3),neglex(3) term order
    1212         """
    1213         if other is None:
     1671            Block term order with blocks:
     1672            (Degree lexicographic term order of length 2,
     1673             Degree reverse lexicographic term order of length 3,
     1674             Negative lexicographic term order of length 3)
     1675        """   
     1676        if isinstance(other, TermOrder):
     1677            return TermOrder('block',[self,other])
     1678        else:
    12141679            return self
    1215        
    1216         if not isinstance(other,TermOrder):
    1217             other = TermOrder(other, force = self.__force)
    1218         if len(self) == 0 or len(other) == 0:
    1219             raise ArithmeticError, "Can only concatenate term orders with length attribute."
    1220 
    1221         name = []
    1222         for block_order in self.blocks + other.blocks:
    1223             if 'M' in block_order.singular_str():
    1224                 raise NotImplementedError, "Cannot use a matrix term order as a block."
    1225             nom = block_order.singular_str()
    1226             name.append("%s(%d)"%(inv_singular_name_mapping.get(nom,nom), len(block_order)))
    1227 
    1228         name = ",".join(name)
    1229         return TermOrder(name, len(self)+len(other), force=self.__force)
    12301680
    12311681    def __len__(self):
    12321682        """
    1233         Return the length of this term ordering, i.e. the number of
     1683        Return the length of this term order, i.e. the number of
    12341684        variables it covers. This may be zero for indefinitely many
    12351685        variables.
    12361686       
     
    12431693            sage: len(T)
    12441694            5
    12451695        """
    1246         return self.__length
     1696        return self._length
    12471697
    12481698    def __getitem__(self, i):
    12491699        r"""
    1250         Return the i-th block of this term ordering.
     1700        Return the i-th block of this term order.
    12511701       
    12521702        INPUT:
    12531703       
     
    12731723            sage: T = TermOrder('lex', 2) + TermOrder('degrevlex', 3)
    12741724            sage: T[len(T)-1]
    12751725            Traceback (most recent call last):
    1276             ...
     1726            \dots
    12771727            IndexError: tuple index out of range
    12781728        """
    1279         return self.blocks[i]
     1729        return self.blocks()[i]
    12801730
    12811731    def __iter__(self):
    12821732        r"""
    1283         Iterate over the blocks of this term ordering.
     1733        Iterate over the blocks of this term order.
    12841734       
    12851735        EXAMPLE::
    12861736       
     
    12991749        the number of variables in ``self`` while the latter
    13001750        counts the number of blocks.
    13011751        """
    1302         return iter(self.blocks)
     1752        return iter(self.blocks())
    13031753
    13041754    def is_global(self):
    13051755        r"""
    1306         Return ``True`` if this term ordering is definitely
    1307         global. Return ``False`` otherwise, which includes
    1308         unknown term orderings.
     1756        Return true if this term order is definitely
     1757        global. Return false otherwise, which includes
     1758        unknown term orders.
    13091759       
    13101760        EXAMPLE::
    13111761       
     
    13191769            sage: T.is_global()
    13201770            False
    13211771        """
    1322         if len(self.blocks) == 1:
    1323             if self.singular_str() in ('lp','dp','Dp'):
    1324                 return True
    1325             else:
    1326                 return False
     1772        if self.name() in ('lex','degrevlex','deglex','wdegrevlex','wdeglex'):
     1773            return True
     1774        elif self.name() is 'block':
     1775            return all([t.is_global() for t in self.blocks()])
    13271776        else:
    1328             return all([t.is_global() for t in self.blocks])
    1329            
     1777            return False
     1778
    13301779    def is_local(self):
    13311780        r"""
    1332         Return ``True`` if this term ordering is definitely
    1333         local. Return ``False`` otherwise, which includes
    1334         unknown term orderings.
     1781        Return true if this term order is definitely
     1782        local. Return false otherwise, which includes
     1783        unknown term orders.
    13351784       
    13361785        EXAMPLE::
    13371786       
     
    13451794            sage: T.is_local()
    13461795            False
    13471796        """
    1348         if len(self.blocks) == 1:
    1349             if self.singular_str() in ('rp', 'ls','ds','Ds'):
    1350                 return True
    1351             else:
    1352                 return False
     1797        if (self.name() in ('neglex','negdegrevlex','negdeglex','negwdegrevlex','negwdeglex') or
     1798            self.singular_str() in ('ls','ds','Ds','ws','Ws')):
     1799            return True
     1800        elif self.name() is 'block':
     1801            return all([t.is_local() for t in self.blocks()])
    13531802        else:
    1354             return all([t.is_local() for t in self.blocks])
     1803            return False
     1804
     1805    def is_block_order(self):
     1806        """
     1807        Return true if self is a block term order.
     1808
     1809        EXAMPLE::
     1810
     1811            sage: t=TermOrder('deglex',2)+TermOrder('lex',2)
     1812            sage: t.is_block_order()
     1813            True
     1814        """
     1815        return self._name == 'block'
     1816
     1817    def is_weighted_degree_order(self):
     1818        """
     1819        Return true if self is a weighted degree term order.
     1820
     1821        EXAMPLE::
     1822
     1823            sage: t=TermOrder('wdeglex',(2,3))
     1824            sage: t.is_weighted_degree_order()
     1825            True
     1826        """           
     1827        return self._weights is not None