Ticket #11316: trac_11316.patch

File trac_11316.patch, 75.2 KB (added by klee, 10 years ago)
  • sage/crypto/mq/sr.py

    # HG changeset patch
    # User Kwankyu Lee <ekwankyu@gmail.com>
    # Date 1305014300 -32400
    # Node ID 294bf6fe3ba390d9c7c3145dd28d7c7bff605626
    # Parent  fb00ec75853019eb9799fd863b193fe82ee97c74
    #11316: added weighted degree term orders
    
    diff -r fb00ec758530 -r 294bf6fe3ba3 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 fb00ec758530 -r 294bf6fe3ba3 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 fb00ec758530 -r 294bf6fe3ba3 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 fb00ec758530 -r 294bf6fe3ba3 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 fb00ec758530 -r 294bf6fe3ba3 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 fb00ec758530 -r 294bf6fe3ba3 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 fb00ec758530 -r 294bf6fe3ba3 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 fb00ec758530 -r 294bf6fe3ba3 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 __init__(self, name='lex', n=0, blocks=True, force=False):
    389510        """
    390         Construct a new term ordering object.
     511        Construct a new term order object.
    391512       
    392513        INPUT:
    393514       
    394         - ``name`` - name of the term ordering (default: lex)
     515        - ``name`` - name of the term order (default: lex)
    395516       
    396         - ``n`` - number of variables in the polynomial ring
    397            (default: 0)
     517        - ``n`` - number of variables (default is `0`) or weights for
     518          weighted degree orders
     519
     520        - ``blocks`` - this is deprecated.
    398521       
    399         - ``blocks`` - controls whether a list of blocks is
    400            maintained (internal use only, default:True)
    401 
    402         - ``force`` - ignore unknown term orderings.
     522        - ``force`` - ignore unknown term orders.
    403523       
    404524        See the ``sage.rings.polynomial.term_order`` module
    405         for help which names and orderings are available.
     525        for help which names and orders are available.
    406526       
    407527        EXAMPLES::
    408528       
     
    412532            sage: loads(dumps(t)) == t
    413533            True
    414534       
    415         We can construct block orderings directly as
     535        We can construct block orders directly as
    416536       
    417537        ::
    418538       
    419539            sage: TermOrder('degrevlex(3),neglex(2)')
    420             degrevlex(3),neglex(2) term order
     540            Block term order with blocks:
     541            (Degree reverse lexicographic term order of length 3,
     542             Negative lexicographic term order of length 2)
    421543       
    422544        or by adding together the blocks::
    423545       
    424546            sage: t1 = TermOrder('degrevlex',3)
    425547            sage: t2 = TermOrder('neglex',2)
    426548            sage: t1 + t2
    427             degrevlex(3),neglex(2) term order
    428             sage: t2 + t1
    429             neglex(2),degrevlex(3) term order
     549            Block term order with blocks:
     550            (Degree reverse lexicographic term order of length 3,
     551             Negative lexicographic term order of length 2)
     552            sage: t3 = TermOrder('wdeglex',(1,2))
     553            sage: t1 + t3
     554            Block term order with blocks:
     555            (Degree reverse lexicographic term order of length 3,
     556             Weighted degree lexicographic term order with weights (1, 2))
    430557       
    431558        .. note::
    432559
    433560           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
     561           non-block orders like `deglex` are
     562           constructed. However, it is useful if block orders are
    436563           to be constructed from this ``TermOrder`` object later.
    437         """
     564        """ 
    438565        if isinstance(name, TermOrder):
    439             if n == 0 and len(name) > 0:
    440                 n = len(name)
     566            self.__copy(name)
     567            if n > 0 and not name.is_block_order() and not name.is_weighted_degree_order():
     568                self.__length = n
     569            return 
     570
     571        if isinstance(name, str): 
     572            name = name.lower()
     573        else:
    441574            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()])+')'
     575                if not isinstance(name, (tuple,list)):
     576                    name = name.list() # name may be a matrix
     577                name = tuple(name)
    449578            except:
    450                 pass
    451         name = name.lower()
     579                raise TypeError, "%s is not a valid term order"%(name,)
    452580
    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)
     581        self.__blocks = tuple()
     582        self.__weights = None
     583        self.__matrix = None
    466584
    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
     585        if name == "block": # block term order with blocks in a list
    515586            length = 0
    516587            blocks = []
    517588            name_str = []
    518589            singular_str = []
    519590            macaulay2_str = []
    520591
    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,)
     592            for t in n:
     593                if not isinstance(t, TermOrder):
     594                    try:
     595                        t = TermOrder(t,force=True)
     596                    except:
     597                        raise TypeError
     598                if t.name() == 'block':
     599                    blocks = blocks + list(t.blocks())
     600                    singular_str.append("%s"%(t.singular_str()[1:-1],))  # [1:-1] is needed to remove parenthesis
     601                    macaulay2_str.append("%s"%(t.macaulay2_str()[1:-1],)) 
     602                else:
     603                    if len(t) == 0:
     604                        raise ArithmeticError, "Can only concatenate term orders with length attribute."   
     605                    blocks.append(t)
     606                    if t.is_weighted_degree_order(): # true if t is a matrix order as well
     607                        singular_str.append("%s"%(t.singular_str(),))
     608                    else:
     609                        singular_str.append("%s(%d)"%(t.singular_str(), len(t)))                                           
     610                    macaulay2_str.append("%s => %d"%(t.macaulay2_str(), len(t)))
     611                length += len(t)
    526612
    527                 block_length = int(block_length)
     613            self.__length = length
     614            self.__name = "block"
     615            self.__singular_str = "(" + ",".join(singular_str) + ")"
     616            self.__macaulay2_str = "{" + ",".join(macaulay2_str) + "}"
     617            self.__magma_str = "" # Magma does not support block order
     618            self.__blocks = tuple(blocks)
     619        elif isinstance(name, str) and not (isinstance(n, tuple) or isinstance(n,list)): # string representation of simple or block orders
     620            split_pattern = "([^(),]+(?:\([^()]*\)[^(),]*)*)" # split by outermost commas         
     621            block_names = re.findall(split_pattern,name)
    528622
    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))
     623            if len(block_names) == 0:
     624                raise TypeError, "No term order specified"
     625            elif len(block_names) == 1:
     626                name = block_names[0]
     627                match = re.match('m\(([-+0-9,]+)\)$',name)
     628                if match: # matrix term order
     629                    m = map(int,match.groups()[0].split(',')) # replace match.groups()[0]  with match.group(1) later
     630                    self.__copy(TermOrder(m))
     631                else: # simple order
     632                    if name not in print_name_mapping.keys() and name not in singular_name_mapping.values() and not force:
     633                        raise TypeError, "Unknown term order '%s'"%(name,)
     634                    self.__length = n
     635                    self.__name = name
     636                    self.__singular_str = singular_name_mapping.get(name,name)
     637                    self.__macaulay2_str = macaulay2_name_mapping.get(name,name)
     638                    self.__magma_str = magma_name_mapping.get(name,name)               
     639            else: # len(block_names) > 1, and hence block order represented by a string
     640                length = 0
     641                blocks = []
     642                name_str = []
     643                singular_str = []
     644                macaulay2_str = []
    533645
    534                 length += block_length
     646                for block in block_names:
     647                    try:
     648                        length_pattern  = re.compile("\(([0-9]+)\)$") # match with parenthesized block length at end                 
     649                        block_name, block_length, _ = re.split(length_pattern,block)
     650                        block_length = int(block_length)
     651                        blocks.append( TermOrder(block_name,block_length,force=force) )
     652                    except:
     653                        raise TypeError, "%s is not a valid term order"%(name,)
     654                    length += block_length
    535655
    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
     656                if n != 0 and length != n:
     657                    raise TypeError, "Term order length does not match the number of generators"
     658                self.__copy(TermOrder('block', blocks))
     659        elif isinstance(name, str) and (isinstance(n, tuple) or isinstance(n,list)): # weighted degree term orders
     660            if name not in print_name_mapping.keys() and name not in singular_name_mapping.values() and not force:
     661                raise TypeError, "Unknown term order '%s'"%(name,) 
     662            weights = tuple(n) # n is a tuple of weights
     663           
     664            self.__length = len(weights)
     665            self.__name = name
     666            self.__singular_str = singular_name_mapping.get(name,name) + '(' + ','.join([str(w) for w in weights]) + ')'
     667            self.__macaulay2_str = ""
     668            self.__magma_str = ""
     669            self.__weights = weights # defined only for weighted degree orders                   
     670        elif isinstance(name, tuple): # name represents a matrix 
     671            if n == 0:
     672                from math import sqrt
     673                n = int(sqrt(len(name)))                   
     674            if n**2 != len(name):
     675                raise TypeError, "%s does not specify a square matrix"%(name,)   
    542676
    543             if n != 0 and self.__length != n:
    544                 raise TypeError, "Term order length does not match the number of generators"
     677            int_str = ','.join([str(int(e)) for e in name])
     678
     679            self.__length = n
     680            self.__name = "matrix"
     681            self.__singular_str = "M(%s)"%(int_str,)
     682            self.__macaulay2_str = "" # Macaulay2 does not support matrix term order directly
     683            self.__magma_str = '"weight",[%s]'%(int_str,)
     684
     685            from sage.matrix.constructor import matrix   
     686            self.__matrix = matrix(n,name)  # defined only for matrix term order
     687            self.__weights = name[:n] # the first row of the matrix gives weights
     688        else:
     689            raise TypeError, "%s is not a valid term order"%(name,)   
     690
     691        self.__doc__ = description_mapping.get(self.__name, "No description available")                 
     692
     693    def __copy(self, other):
     694        """
     695        Copy other term order to self.
     696
     697        EXAMPLE::
     698       
     699            sage: t = TermOrder('lex')
     700            sage: s = TermOrder(t)
     701            sage: t == s            # indirect test
     702            True
     703        """
     704        self.__length = other._TermOrder__length
     705        self.__name = other._TermOrder__name
     706        self.__singular_str = other._TermOrder__singular_str
     707        self.__macaulay2_str = other._TermOrder__macaulay2_str
     708        self.__magma_str = other._TermOrder__magma_str
     709        self.__blocks = other._TermOrder__blocks
     710
     711        self.__matrix = other._TermOrder__matrix
     712        self.__weights = other._TermOrder__weights
    545713
    546714    def __getattr__(self,name):
    547715        """
     
    550718        EXAMPLE::
    551719       
    552720            sage: TermOrder('lex').compare_tuples
    553             <bound method TermOrder.compare_tuples_lp of Lexicographic term order>
     721            <bound method TermOrder.compare_tuples_lex of Lexicographic term order>
    554722       
    555723        ::
    556724       
    557725            sage: TermOrder('deglex').compare_tuples
    558             <bound method TermOrder.compare_tuples_Dp of Degree lexicographic term order>
     726            <bound method TermOrder.compare_tuples_deglex of Degree lexicographic term order>
    559727        """
    560728        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
     729            return getattr(self,'compare_tuples_'+self.__name)
    568730        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
     731            return getattr(self,'greater_tuple_'+self.__name)
    576732        else:
    577733            raise AttributeError,name
    578734
     
    596752            False
    597753        """
    598754        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))
     755            sf = sum(l*r for (l,r) in zip(row,f))
     756            sg = sum(l*r for (l,r) in zip(row,g))
    601757       
    602             if mf > mg:
     758            if sf > sg:
    603759                return 1
    604             elif mf < mg:
     760            elif sf < sg:
    605761                return -1
    606762        return 0 
    607763
    608     def compare_tuples_lp(self,f,g):
     764    def compare_tuples_lex(self,f,g):
    609765        """
    610766        Compares two exponent tuples with respect to the lexicographical
    611767        term order.
     
    624780            sage: x > 1
    625781            True
    626782        """
    627 
    628         if f>g:
     783        if f > g:
    629784            return 1
    630         elif f<g:
     785        elif f < g:
    631786            return -1
    632787        else:
    633788            return 0
    634789
    635     def compare_tuples_rp(self,f,g):
     790    def compare_tuples_invlex(self,f,g):
    636791        """
    637792        Compares two exponent tuples with respect to the inversed
    638793        lexicographical term order.
     
    651806            sage: x > 1
    652807            True
    653808        """
    654         return self.compare_tuples_lp(f.reversed(),g.reversed())
     809        return self.compare_tuples_lex(f.reversed(),g.reversed())
    655810
    656     def compare_tuples_Dp(self,f,g):
     811    def compare_tuples_deglex(self,f,g):
    657812        """
    658813        Compares two exponent tuples with respect to the degree
    659814        lexicographical term order.
     
    676831        sg = sum(g.nonzero_values(sort=False))
    677832        if sf > sg:
    678833            return 1
    679         elif sf<sg:
     834        elif sf < sg:
    680835            return -1
    681836        elif sf == sg:
    682             return self.compare_tuples_lp(f,g)
     837            return self.compare_tuples_lex(f,g)
    683838
    684     def compare_tuples_dp(self,f,g):
     839    def compare_tuples_degrevlex(self,f,g):
    685840        """
    686841        Compares two exponent tuples with respect to the degree reversed
    687842        lexicographical term order.
     
    704859        sg = sum(g.nonzero_values(sort=False))
    705860        if sf > sg:
    706861            return 1
    707         elif sf<sg:
     862        elif sf < sg:
    708863            return -1
    709864        elif sf == sg:
    710             return (-1)*self.compare_tuples_lp(f.reversed(),g.reversed())
     865            return -self.compare_tuples_lex(f.reversed(),g.reversed())
    711866
    712     def compare_tuples_ls(self,f,g):
     867    def compare_tuples_neglex(self,f,g):
    713868        """
    714869        Compares two exponent tuples with respect to the negative
    715870        lexicographical term order.
     
    728883            sage: x > 1
    729884            False
    730885        """
    731         return -self.compare_tuples_lp(f,g)
     886        return -self.compare_tuples_lex(f,g)
    732887
    733     def compare_tuples_ds(self,f,g):
     888    def compare_tuples_negdegrevlex(self,f,g):
    734889        """
    735890        Compares two exponent tuples with respect to the negative degree
    736891        reverse lexicographical term order.
     
    753908        sg = sum(g.nonzero_values(sort=False))
    754909        if sf > sg:
    755910            return -1
    756         elif sf<sg:
     911        elif sf < sg:
    757912            return 1
    758913        elif sf == sg:
    759             return (-1)*self.compare_tuples_lp(f.reversed(),g.reversed())
     914            return (-1)*self.compare_tuples_lex(f.reversed(),g.reversed())
    760915
    761     def compare_tuples_Ds(self,f,g):
     916    def compare_tuples_negdeglex(self,f,g):
    762917        """
    763918        Compares two exponent tuples with respect to the negative degree
    764919        lexicographical term order.
     
    781936        sg = sum(g.nonzero_values(sort=False))
    782937        if sf > sg:
    783938            return -1
    784         elif sf<sg:
     939        elif sf < sg:
    785940            return 1
    786941        elif sf == sg:
    787             return self.compare_tuples_lp(f,g)
     942            return self.compare_tuples_lex(f,g)
     943
     944    def compare_tuples_wdegrevlex(self,f,g):
     945        """
     946        Compares two exponent tuples with respect to the weighted degree reverse
     947        lexicographical term order.
     948       
     949        INPUT:
     950       
     951        - ``f`` - exponent tuple
     952       
     953        - ``g`` - exponent tuple
     954       
     955        EXAMPLE::
     956 
     957            sage: t = TermOrder('wdegrevlex',(3,2)) 
     958            sage: P.<x,y> = PolynomialRing(QQbar, 2, order=t)
     959            sage: x > y^2 # indirect doctest
     960            False
     961            sage: x^2 > y^3
     962            True
     963        """
     964        sf = sum(l*r for (l,r) in zip(f,self.__weights))
     965        sg = sum(l*r for (l,r) in zip(g,self.__weights)) 
     966        if sf > sg:
     967            return 1
     968        elif sf < sg:
     969            return -1
     970        elif sf == sg:
     971            return -self.compare_tuples_lex(f.reversed(),g.reversed()) 
     972
     973    def compare_tuples_wdeglex(self,f,g):
     974        """
     975        Compares two exponent tuples with respect to the weighted degree
     976        lexicographical term order.
     977       
     978        INPUT:
     979       
     980        - ``f`` - exponent tuple
     981       
     982        - ``g`` - exponent tuple
     983       
     984        EXAMPLE::
     985       
     986            sage: t = TermOrder('wdeglex',(3,2))
     987            sage: P.<x,y> = PolynomialRing(QQbar, 2, order=t)
     988            sage: x > y^2 # indirect doctest
     989            False
     990            sage: x > y
     991            True
     992        """
     993        sf = sum(l*r for (l,r) in zip(f,self.__weights))
     994        sg = sum(l*r for (l,r) in zip(g,self.__weights)) 
     995        if sf > sg:
     996            return 1
     997        elif sf < sg:
     998            return -1
     999        elif sf == sg:
     1000            return self.compare_tuples_lex(f,g)   
     1001
     1002    def compare_tuples_negwdeglex(self,f,g):
     1003        """
     1004        Compares two exponent tuples with respect to the negative weighted
     1005        degree lexicographical term order.
     1006       
     1007        INPUT:
     1008       
     1009        - ``f`` - exponent tuple
     1010       
     1011        - ``g`` - exponent tuple
     1012       
     1013        EXAMPLE::
     1014
     1015            sage: t = TermOrder('negwdeglex',(3,2)) 
     1016            sage: P.<x,y> = PolynomialRing(QQbar, 2, order=t)
     1017            sage: x > y^2 # indirect doctest
     1018            True
     1019            sage: x^2 > y^3
     1020            True
     1021        """
     1022        sf = sum(l*r for (l,r) in zip(f,self.__weights))
     1023        sg = sum(l*r for (l,r) in zip(g,self.__weights)) 
     1024        if sf > sg:
     1025            return -1
     1026        elif sf < sg:
     1027            return 1
     1028        elif sf == sg:
     1029            return self.compare_tuples_lex(f,g) 
     1030 
     1031    def compare_tuples_negwdegrevlex(self,f,g):
     1032        """
     1033        Compares two exponent tuples with respect to the negative weighted
     1034        degree reverse lexicographical term order.
     1035       
     1036        INPUT:
     1037       
     1038        - ``f`` - exponent tuple
     1039       
     1040        - ``g`` - exponent tuple
     1041       
     1042        EXAMPLE::
     1043 
     1044             sage: t = TermOrder('negwdegrevlex',(3,2))   
     1045            sage: P.<x,y> = PolynomialRing(QQbar, 2, order=t)
     1046            sage: x > y^2 # indirect doctest
     1047            True
     1048            sage: x^2 > y^3
     1049            True
     1050        """
     1051        sf = sum(l*r for (l,r) in zip(f,self.__weights))
     1052        sg = sum(l*r for (l,r) in zip(g,self.__weights))   
     1053        if sf > sg:
     1054            return -1
     1055        elif sf < sg:
     1056            return 1
     1057        elif sf == sg:
     1058            return (-1)*self.compare_tuples_lex(f.reversed(),g.reversed())
    7881059
    7891060    def compare_tuples_block(self, f,g):
    7901061        """
    791         Compares two exponent tuples with respect to the block ordering as
     1062        Compares two exponent tuples with respect to the block order as
    7921063        specified when constructing this element.
    7931064       
    7941065        INPUT:
     
    8061077            True
    8071078        """
    8081079        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)])
     1080        for block in self:
     1081            r = getattr(block,"compare_tuples_" + block.name())(f[n:n+len(block)],g[n:n+len(block)])
    8111082            if r != 0:
    8121083                return r
    813             n += len(order)
     1084            n += len(block)
    8141085        return 0
    8151086
    8161087    def greater_tuple_matrix(self,f,g):
     
    8331104            False
    8341105        """
    8351106        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))
     1107            sf = sum(l*r for (l,r) in zip(row,f))
     1108            sg = sum(l*r for (l,r) in zip(row,g))
    8381109       
    839             if mf>mg:
     1110            if sf > sg:
    8401111                return f
    841             elif mf<mg:
     1112            elif sf < sg:
    8421113                return g
    8431114        return g   
    8441115
    845     def greater_tuple_lp(self,f,g):
     1116    def greater_tuple_lex(self,f,g):
    8461117        """
    847         Returns the greater exponent tuple with respect to the
     1118        Return the greater exponent tuple with respect to the
    8481119        lexicographical term order.
    8491120       
    8501121        INPUT:
     
    8641135        """
    8651136        return f > g and f or g
    8661137
    867     def greater_tuple_rp(self,f,g):
     1138    def greater_tuple_invlex(self,f,g):
    8681139        """
    869         Returns the greater exponent tuple with respect to the inversed
     1140        Return the greater exponent tuple with respect to the inversed
    8701141        lexicographical term order.
    8711142       
    8721143        INPUT:
     
    8861157        This method is called by the lm/lc/lt methods of
    8871158        ``MPolynomial_polydict``.
    8881159        """
    889         return f.reversed() > g.reversed()   and f or g
     1160        return f.reversed() > g.reversed() and f or g
    8901161       
    891     def greater_tuple_Dp(self,f,g):
     1162    def greater_tuple_deglex(self,f,g):
    8921163        """
    893         Returns the greater exponent tuple with respect to the total degree
     1164        Return the greater exponent tuple with respect to the total degree
    8941165        lexicographical term order.
    8951166       
    8961167        INPUT:
     
    9101181        This method is called by the lm/lc/lt methods of
    9111182        ``MPolynomial_polydict``.
    9121183        """
    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
     1184        sf = sum(f.nonzero_values(sort=False))
     1185        sg = sum(g.nonzero_values(sort=False))
     1186        return ( sf > sg or ( sf == sg and f  > g )) and f or g
    9151187   
    916     def greater_tuple_dp(self,f,g):
     1188    def greater_tuple_degrevlex(self,f,g):
    9171189        """
    918         Returns the greater exponent tuple with respect to the total degree
     1190        Return the greater exponent tuple with respect to the total degree
    9191191        reversed lexicographical term order.
    9201192       
    9211193        INPUT:
     
    9351207        This method is called by the lm/lc/lt methods of
    9361208        ``MPolynomial_polydict``.
    9371209        """
    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
     1210        sf = sum(f.nonzero_values(sort=False))
     1211        sg = sum(g.nonzero_values(sort=False))
     1212        return ( sf > sg or ( sf == sg and f.reversed() < g.reversed() )) and f or g         
    9411213   
    942     def greater_tuple_ds(self,f,g):
     1214    def greater_tuple_negdegrevlex(self,f,g):
    9431215        """
    944         Returns the greater exponent tuple with respect to the negative
     1216        Return the greater exponent tuple with respect to the negative
    9451217        degree reverse lexicographical term order.
    9461218       
    9471219        INPUT:
     
    9631235        This method is called by the lm/lc/lt methods of
    9641236        ``MPolynomial_polydict``.
    9651237        """
    966         if self.compare_tuples_ds(f,g) >= 0:
    967             return f
    968         else:
    969             return g
     1238        sf = sum(f.nonzero_values(sort=False))
     1239        sg = sum(g.nonzero_values(sort=False))
     1240        return ( sf < sg or ( sf == sg and f.reversed() < g.reversed() )) and f or g
    9701241
    971     def greater_tuple_Ds(self,f,g):
     1242    def greater_tuple_negdeglex(self,f,g):
    9721243        """
    973         Returns the greater exponent tuple with respect to the negative
     1244        Return the greater exponent tuple with respect to the negative
    9741245        degree lexicographical term order.
    9751246       
    9761247        INPUT:
     
    9921263        This method is called by the lm/lc/lt methods of
    9931264        ``MPolynomial_polydict``.
    9941265        """
    995         if self.compare_tuples_Ds(f,g) >= 0:
    996             return f
    997         else:
    998             return g
     1266        sf = sum(f.nonzero_values(sort=False))
     1267        sg = sum(g.nonzero_values(sort=False))
     1268        return ( sf < sg or ( sf == sg and f  > g )) and f or g   
    9991269
    1000     def greater_tuple_ls(self,f,g):
     1270    def greater_tuple_neglex(self,f,g):
    10011271        """
    1002         Returns the greater exponent tuple with respect to the negative
     1272        Return the greater exponent tuple with respect to the negative
    10031273        lexicographical term order.
    10041274       
    10051275        This method is called by the lm/lc/lt methods of
     
    10191289            sage: g = a + e^4; g.lm()
    10201290            a
    10211291        """
    1022         if self.greater_tuple_lp(f,g) is f:
    1023             return g
    1024         else:
    1025             return f
     1292        return (f < g) and f or g
    10261293
     1294    def greater_tuple_wdeglex(self,f,g):
     1295        """
     1296        Return the greater exponent tuple with respect to the weighted degree
     1297        lexicographical term order.
     1298       
     1299        INPUT:
     1300       
     1301        - ``f`` - exponent tuple
     1302       
     1303        - ``g`` - exponent tuple
     1304       
     1305        EXAMPLE::
     1306
     1307            sage: t = TermOrder('wdeglex',(1,2,3))
     1308            sage: P.<x,y,z> = PolynomialRing(QQbar, 3, order=t)
     1309            sage: f = x + y; f.lm() # indirect doctest
     1310            y
     1311            sage: f = x*y + z; f.lm()
     1312            x*y
     1313       
     1314        This method is called by the lm/lc/lt methods of
     1315        ``MPolynomial_polydict``.
     1316        """
     1317        sf = sum(l*r for (l,r) in zip(f,self.__weights))
     1318        sg = sum(l*r for (l,r) in zip(g,self.__weights))         
     1319        return (sf > sg or ( sf == sg and f  > g )) and f or g   
     1320 
     1321    def greater_tuple_wdegrevlex(self,f,g):
     1322        """
     1323        Return the greater exponent tuple with respect to the weighted degree
     1324        reverse lexicographical term order.
     1325       
     1326        INPUT:
     1327       
     1328        - ``f`` - exponent tuple
     1329       
     1330        - ``g`` - exponent tuple
     1331       
     1332        EXAMPLES::
     1333       
     1334            sage: t = TermOrder('wdegrevlex',(1,2,3))
     1335            sage: P.<x,y,z> = PolynomialRing(QQbar, 3, order=t)
     1336            sage: f = x + y; f.lm() # indirect doctest
     1337            y
     1338            sage: f = x + y^2*z; f.lm()
     1339            y^2*z
     1340       
     1341        This method is called by the lm/lc/lt methods of
     1342        ``MPolynomial_polydict``.
     1343        """
     1344        sf = sum(l*r for (l,r) in zip(f,self.__weights))
     1345        sg = sum(l*r for (l,r) in zip(g,self.__weights))         
     1346        return (sf > sg or ( sf == sg and f.reversed() < g.reversed())) and f or g 
     1347
     1348    def greater_tuple_negwdeglex(self,f,g):
     1349        """
     1350        Return the greater exponent tuple with respect to the negative
     1351        weighted degree lexicographical term order.
     1352       
     1353        INPUT:
     1354       
     1355        - ``f`` - exponent tuple
     1356       
     1357        - ``g`` - exponent tuple
     1358       
     1359        EXAMPLE::
     1360       
     1361            sage: t = TermOrder('negwdeglex',(1,2,3))
     1362            sage: P.<x,y,z> = PolynomialRing(QQbar, 3, order=t) 
     1363            sage: f = x + y; f.lm() # indirect doctest
     1364            x
     1365            sage: f = x + x^2; f.lm()
     1366            x
     1367            sage: f = x^3 + z; f.lm()
     1368            x^3
     1369       
     1370        This method is called by the lm/lc/lt methods of
     1371        ``MPolynomial_polydict``.
     1372        """
     1373        sf = sum(l*r for (l,r) in zip(f,self.__weights))
     1374        sg = sum(l*r for (l,r) in zip(g,self.__weights)) 
     1375        return (sf < sg or ( sf == sg and f  > g )) and f or g 
     1376
     1377    def greater_tuple_negwdegrevlex(self,f,g):
     1378        """
     1379        Return the greater exponent tuple with respect to the negative
     1380        weighted degree reverse lexicographical term order.
     1381       
     1382        INPUT:
     1383       
     1384        - ``f`` - exponent tuple
     1385       
     1386        - ``g`` - exponent tuple
     1387       
     1388        EXAMPLE::
     1389       
     1390            sage: t = TermOrder('negwdegrevlex',(1,2,3))
     1391            sage: P.<x,y,z> = PolynomialRing(QQbar, 3, order=t)
     1392            sage: f = x + y; f.lm() # indirect doctest
     1393            x
     1394            sage: f = x + x^2; f.lm()
     1395            x
     1396            sage: f = x^3 + z; f.lm() 
     1397            x^3
     1398       
     1399        This method is called by the lm/lc/lt methods of
     1400        ``MPolynomial_polydict``.
     1401        """
     1402        sf = sum(l*r for (l,r) in zip(f,self.__weights))
     1403        sg = sum(l*r for (l,r) in zip(g,self.__weights)) 
     1404        return (sf < sg or ( sf == sg and f.reversed() < g.reversed() )) and f or g   
     1405       
    10271406    def greater_tuple_block(self, f,g):
    10281407        """
    1029         Returns the greater exponent tuple with respect to the block
    1030         ordering as specified when constructing this element.
     1408        Return the greater exponent tuple with respect to the block
     1409        order as specified when constructing this element.
    10311410       
    10321411        This method is called by the lm/lc/lt methods of
    10331412        ``MPolynomial_polydict``.
     
    10471426            a
    10481427        """
    10491428        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)])
     1429        for block in self:
     1430            r = getattr(block,"compare_tuples_" + block.name())(f[n:n+len(block)],g[n:n+len(block)])
    10521431            if r != 0:
    10531432                if r < 0:
    10541433                    return g
    10551434                else:
    10561435                    return f
    1057             n += len(order)
     1436            n += len(block)
    10581437        return f
    10591438
     1439    def tuple_weight(self, f):
     1440        """
     1441        Return the weight of tuple f.
     1442
     1443        INPUT:
     1444       
     1445        - ``f`` - exponent tuple 
     1446
     1447        EXAMPLE::   
     1448
     1449            sage: t=TermOrder('wdeglex',(1,2,3))
     1450            sage: P.<a,b,c>=PolynomialRing(QQbar, order=t)
     1451            sage: P.term_order().tuple_weight([3,2,1])
     1452            10
     1453        """
     1454        return sum(l*r for (l,r) in zip(f,self.__weights))
     1455
    10601456    def name(self):
    10611457        """
    10621458        EXAMPLE::
     
    10731469            sage: TermOrder('lex') # indirect doctest
    10741470            Lexicographic term order
    10751471        """
    1076         if self.__name[0] == 'M':
    1077             return 'Matrix term order with matrix\n%s'%self.matrix()
     1472        if self.__name == 'matrix':
     1473            return 'Matrix term order with matrix\n%s'%(self.__matrix,)
     1474        elif self.__name == 'block':
     1475            s = []
     1476            for t in self.__blocks:
     1477                if not t.is_weighted_degree_order():
     1478                    s.append('%s of length %d'%(t,len(t)))
     1479                else: # includes matrix order
     1480                    s.append('%s'%(t,))
     1481            return 'Block term order with blocks:\n(%s)'%(',\n '.join(s),)
    10781482        else:
    1079             s = print_name_mapping.get(self.__name,self.__name)
    1080             return '%s term order'%s
     1483            s = print_name_mapping.get(self.__name,self.__name) + ' term order'
     1484            if self.is_weighted_degree_order():
     1485                s = s + ' with weights %s'%(self.__weights,)
     1486            return s
    10811487
    10821488    def singular_str(self):
    10831489        """
     
    11161522            sage: P = PolynomialRing(GF(127), 8,names='x',order='degrevlex(3),lex(5)')
    11171523            sage: T = P.term_order()
    11181524            sage: T.macaulay2_str()
    1119             '(GRevLex => 3,Lex => 5)'
     1525            '{GRevLex => 3,Lex => 5}'
    11201526            sage: P._macaulay2_() # optional - macaulay2
    11211527            ZZ/127 [x0, x1, x2, x3, x4, x5, x6, x7, MonomialOrder => {GRevLex => 3, Lex => 5}, MonomialSize => 16]
    11221528        """
     
    11441550        """
    11451551        return self.__magma_str
    11461552
     1553    def blocks(self):
     1554        """
     1555        Return the term order blocks of self.
     1556
     1557        EXAMPLE::
     1558
     1559            sage: t=TermOrder('deglex',2)+TermOrder('lex',2)
     1560            sage: t.blocks()
     1561            (Degree lexicographic term order, Lexicographic term order)
     1562        """
     1563        if self.__blocks: # self is a block order
     1564            return self.__blocks
     1565        else:
     1566            return [self]
     1567
    11471568    def matrix(self):   
    11481569        """
    1149         Return the matrix defining matrix ordering.
     1570        Return the matrix defining matrix term order.
    11501571
    11511572        EXAMPLE::
    11521573
     
    11561577            [0 1]
    11571578           
    11581579        """
    1159         from sage.matrix.constructor import matrix
    1160         return matrix(self.__matrix)
     1580        return self.__matrix
    11611581
    1162     def __cmp__(self, other):
     1582    def weights(self):
    11631583        """
    1164         Only equality testing makes sense here.
    1165        
     1584        Return the weights for weighted term orders.
     1585
     1586        EXAMPLE::
     1587
     1588            sage: t=TermOrder('wdeglex',(2,3))
     1589            sage: t.weights()
     1590            (2, 3)
     1591        """           
     1592        return self.__weights
     1593
     1594    def __eq__(self, other):
     1595        """
     1596        Return true if self and other are equal.
     1597
    11661598        EXAMPLE::
    11671599       
    11681600            sage: TermOrder('lex') == TermOrder('lex',3)
     
    11781610            sage: T1 = TermOrder('lex',2)+TermOrder('lex',3)
    11791611            sage: T2 = TermOrder('lex',3)+TermOrder('lex',2)
    11801612            sage: T1 == T2
    1181             False
     1613            True
    11821614       
    11831615        ::
    11841616       
     
    11881620            True
    11891621        """
    11901622        if not isinstance(other, TermOrder):
    1191             if isinstance(other, str):
     1623            try:
    11921624                other = TermOrder(other, force=True)
    1193             else:
    1194                 return cmp(type(self), type(other))
    1195         return cmp(self.singular_str(), other.singular_str())
     1625            except:
     1626                return False
     1627
     1628        return (self.__name == other.__name       # note that length is not considered.
     1629            and self.__blocks == other.__blocks
     1630            and self.__weights == other.__weights
     1631            and self.__matrix == other.__matrix)
     1632
     1633    def __ne__(self, other):
     1634        """
     1635        Return true if self and other are not equal.
     1636
     1637        EXAMPLE::
     1638       
     1639            sage: T1 = TermOrder('lex',2)+TermOrder('lex',3)
     1640            sage: T2 = TermOrder('lex',3)+TermOrder('lex',2)
     1641            sage: T1 != T2
     1642            False 
     1643        """
     1644        return not self.__eq__(other)
    11961645
    11971646    def __add__(self, other):
    11981647        """
    1199         Block ordering constructor.
     1648        Construct a block order combining self and other.
    12001649       
    12011650        INPUT:
    12021651       
    12031652        - ``other`` - a term order
    12041653       
    1205         OUTPUT: a block ordering
     1654        OUTPUT: a block order
    12061655       
    12071656        EXAMPLE::
    12081657       
    12091658            sage: from sage.rings.polynomial.term_order import TermOrder
    12101659            sage: TermOrder('deglex',2) + TermOrder('degrevlex(3),neglex(3)')
    1211             deglex(2),degrevlex(3),neglex(3) term order
    1212         """
    1213         if other is None:
     1660            Block term order with blocks:
     1661            (Degree lexicographic term order of length 2,
     1662             Degree reverse lexicographic term order of length 3,
     1663             Negative lexicographic term order of length 3)
     1664        """   
     1665        if isinstance(other, TermOrder):
     1666            return TermOrder('block',[self,other])
     1667        else:
    12141668            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)
    12301669
    12311670    def __len__(self):
    12321671        """
    1233         Return the length of this term ordering, i.e. the number of
     1672        Return the length of this term order, i.e. the number of
    12341673        variables it covers. This may be zero for indefinitely many
    12351674        variables.
    12361675       
     
    12471686
    12481687    def __getitem__(self, i):
    12491688        r"""
    1250         Return the i-th block of this term ordering.
     1689        Return the i-th block of this term order.
    12511690       
    12521691        INPUT:
    12531692       
     
    12731712            sage: T = TermOrder('lex', 2) + TermOrder('degrevlex', 3)
    12741713            sage: T[len(T)-1]
    12751714            Traceback (most recent call last):
    1276             ...
     1715            \dots
    12771716            IndexError: tuple index out of range
    12781717        """
    1279         return self.blocks[i]
     1718        return self.blocks()[i]
    12801719
    12811720    def __iter__(self):
    12821721        r"""
    1283         Iterate over the blocks of this term ordering.
     1722        Iterate over the blocks of this term order.
    12841723       
    12851724        EXAMPLE::
    12861725       
     
    12991738        the number of variables in ``self`` while the latter
    13001739        counts the number of blocks.
    13011740        """
    1302         return iter(self.blocks)
     1741        return iter(self.blocks())
    13031742
    13041743    def is_global(self):
    13051744        r"""
    1306         Return ``True`` if this term ordering is definitely
    1307         global. Return ``False`` otherwise, which includes
    1308         unknown term orderings.
     1745        Return true if this term order is definitely
     1746        global. Return false otherwise, which includes
     1747        unknown term orders.
    13091748       
    13101749        EXAMPLE::
    13111750       
     
    13191758            sage: T.is_global()
    13201759            False
    13211760        """
    1322         if len(self.blocks) == 1:
    1323             if self.singular_str() in ('lp','dp','Dp'):
    1324                 return True
    1325             else:
    1326                 return False
     1761        if self.name() in ('lex','degrevlex','deglex','wdegrevlex','wdeglex'):
     1762            return True
     1763        elif self.name() is 'block':
     1764            return all([t.is_global() for t in self.blocks()])
    13271765        else:
    1328             return all([t.is_global() for t in self.blocks])
    1329            
     1766            return False
     1767
    13301768    def is_local(self):
    13311769        r"""
    1332         Return ``True`` if this term ordering is definitely
    1333         local. Return ``False`` otherwise, which includes
    1334         unknown term orderings.
     1770        Return true if this term order is definitely
     1771        local. Return false otherwise, which includes
     1772        unknown term orders.
    13351773       
    13361774        EXAMPLE::
    13371775       
     
    13451783            sage: T.is_local()
    13461784            False
    13471785        """
    1348         if len(self.blocks) == 1:
    1349             if self.singular_str() in ('rp', 'ls','ds','Ds'):
    1350                 return True
    1351             else:
    1352                 return False
     1786        if (self.name() in ('neglex','negdegrevlex','negdeglex','negwdegrevlex','negwdeglex') or
     1787            self.singular_str() in ('ls','ds','Ds','ws','Ws')):
     1788            return True
     1789        elif self.name() is 'block':
     1790            return all([t.is_local() for t in self.blocks()])
    13531791        else:
    1354             return all([t.is_local() for t in self.blocks])
     1792            return False
     1793
     1794    def is_block_order(self):
     1795        """
     1796        Return true if self is a block term order.
     1797
     1798        EXAMPLE::
     1799
     1800            sage: t=TermOrder('deglex',2)+TermOrder('lex',2)
     1801            sage: t.is_block_order()
     1802            True
     1803        """
     1804        return self.__name == 'block'
     1805
     1806    def is_weighted_degree_order(self):
     1807        """
     1808        Return true if self is a weighted degree term order.
     1809
     1810        EXAMPLE::
     1811
     1812            sage: t=TermOrder('wdeglex',(2,3))
     1813            sage: t.is_weighted_degree_order()
     1814            True
     1815        """           
     1816        return self.__weights is not None