Ticket #12090: trac_12090-review.patch

File trac_12090-review.patch, 17.8 KB (added by hthomas, 8 years ago)
  • sage/geometry/pseudolines.py

    # HG changeset patch
    # User hthomas@unb.ca
    # Date 1369014625 10800
    # Node ID 756a267710a5463b85054d8c1cf3f5f964b6de2d
    # Parent  f398269b85eab62ff1c22230a6def24e5ca76dbb
    implement pseudo-line arrangements (review patch)
    
    diff --git a/sage/geometry/pseudolines.py b/sage/geometry/pseudolines.py
    a b  
    22Pseudolines
    33
    44This module gathers everything that has to do with pseudolines, and for a start
    5 a :class:`PseudolinesArrangement` class that can be used to describe an
     5a :class:`PseudolineArrangement` class that can be used to describe an
    66arrangement of pseudolines in several different ways, and to translate one
    77description into another, as well as to display *Wiring diagrams* via the
    8 :meth:`show <sage.geometry.pseudolines.PseudolinesArrangement.show>` method.
     8:meth:`show <sage.geometry.pseudolines.PseudolineArrangement.show>` method.
    99
    1010In the following, we try to stick to the terminology given in [Felsner]_, which
    1111can be checked in case of doubt. And please fix this module's documentation
     
    1717`x`-monotone curve in the plane. A *set* of pseudolines, however, represents a
    1818set of such curves that pairwise intersect exactly once (and hence mimic the
    1919behaviour of straight lines in general position). We also assume that those
    20 pseudolines are in general position, that is that no three of them cross on the
     20pseudolines are in general position, that is that no three of them cross at the
    2121same point.
    2222
    2323The present class is made to deal with a combinatorial encoding of a pseudolines
     
    2525`l_0, ..., l_{n-1}` crosses the `n-1` other lines.
    2626
    2727.. WARNING::
    28  
     28
    2929    It is assumed through all the methods that the given lines are numbered
    30     consistently : it is not possible that the first transposition be ``(0,2)``
     30    according to their `y`-coordinate on the vertical line `x=-\infty`.
     31    For instance, it is not possible that the first transposition be ``(0,2)``
    3132    (or equivalently that the first line `l_0` crosses is `l_2` and conversely),
    32     for it would mean that one of them cuts `l_1`. It is actually assumed that
    33     the pseudolines are numbered according to their `y`-coordinate on the
    34     vertical line `x=-\infty`.
     33    because one of them would have to cross `l_1` first.
    3534
    3635Encodings
    3736----------
     
    3938**Permutations**
    4039
    4140An arrangement of pseudolines can be described by a sequence of `n` lists of
    42 length `n-1`, where the `i` list is a permutation of `\{1, ..., n\} \backslash
     41length `n-1`, where the `i` list is a permutation of `\{0, ..., n-1\} \backslash
    4342i` representing the ordering in which the `i` th pseudoline meets the other
    4443ones.
    4544
    4645::
    4746
    48     sage: from sage.geometry.pseudolines import PseudolinesArrangement
     47    sage: from sage.geometry.pseudolines import PseudolineArrangement
    4948    sage: permutations = [[3, 2, 1], [3, 2, 0], [3, 1, 0], [2, 1, 0]]
    50     sage: p = PseudolinesArrangement(permutations)
    51     sage: p 
     49    sage: p = PseudolineArrangement(permutations)
     50    sage: p
    5251    Arrangement of pseudolines of size 4
    5352    sage: p.show()
    5453
     
    5958transposition `(2,3)` appears before `(8, 2)` iif `l_2` crosses `l_3` before it
    6059crosses `l_8`. This encoding is easy to obtain by reading the wiring diagram
    6160from left to right (see the :meth:`show
    62 <sage.geometry.pseudolines.PseudolinesArrangement.show>` method).
     61<sage.geometry.pseudolines.PseudolineArrangement.show>` method).
    6362
    6463::
    6564
    66     sage: from sage.geometry.pseudolines import PseudolinesArrangement
     65    sage: from sage.geometry.pseudolines import PseudolineArrangement
    6766    sage: transpositions = [(3, 2), (3, 1), (0, 3), (2, 1), (0, 2), (0, 1)]
    68     sage: p = PseudolinesArrangement(transpositions)
    69     sage: p 
     67    sage: p = PseudolineArrangement(transpositions)
     68    sage: p
    7069    Arrangement of pseudolines of size 4
    7170    sage: p.show()
    7271
     
    107106transpositions, it is sufficient to look for occurrences of
    108107`\begin{array}{c}0\\1\end{array}` in the first column of the matrix, as it
    109108corresponds in the wiring diagram to a line going up while the line immediately
    110 above it does down -- those two lines cross. Each time such a pattern is found
     109above it goes down -- those two lines cross. Each time such a pattern is found
    111110it yields a new transposition, and the matrix can be updated so that this
    112111pattern disappears. A more detailed description of this algorithm is given in
    113112[Felsner]_.
    114113
    115114::
    116115
    117     sage: from sage.geometry.pseudolines import PseudolinesArrangement
     116    sage: from sage.geometry.pseudolines import PseudolineArrangement
    118117    sage: felsner_matrix = [[0, 0, 0], [0, 0, 1], [0, 1, 1], [1, 1, 1]]
    119     sage: p = PseudolinesArrangement(felsner_matrix)
     118    sage: p = PseudolineArrangement(felsner_matrix)
    120119    sage: p
    121120    Arrangement of pseudolines of size 4
    122121
     
    133132    sage: print l[:5]                            # not tested
    134133    [(96, 278.0130613051349), (74, 332.92512282478714), (13, 155.65820951249867), (209, 34.753946221755307), (147, 193.51376457741441)]
    135134    sage: l.sort()
    136     sage: n = len(l)
    137135
    138 We can now compute for each `i` the order in which line `i` meet the other lines::
     136We can now compute for each `i` the order in which line `i` meets the other lines::
    139137
    140138    sage: permutations = [[0..i-1]+[i+1..n-1] for i in range(n)]
    141139    sage: a = lambda x : l[x][0]
    142140    sage: b = lambda x : l[x][1]
    143141    sage: for i, perm in enumerate(permutations):
    144     ...       perm.sort(key = lambda j : (b(j)-b(i))/(a(i)-a(j)))
     142    ....:     perm.sort(key = lambda j : (b(j)-b(i))/(a(i)-a(j)))
    145143
    146144And finally build the line arrangement::
    147145
    148     sage: from sage.geometry.pseudolines import PseudolinesArrangement
    149     sage: p = PseudolinesArrangement(permutations)
     146    sage: from sage.geometry.pseudolines import PseudolineArrangement
     147    sage: p = PseudolineArrangement(permutations)
    150148    sage: print p
    151149    Arrangement of pseudolines of size 20
    152150    sage: p.show(figsize=[20,8])
     
    175173
    176174from copy import deepcopy
    177175
    178 class PseudolinesArrangement:
     176class PseudolineArrangement:
    179177
    180178    def __init__(self, seq, encoding = "auto"):
    181179        r"""
     
    200198           * The pseudolines are assumed to be integers `0..(n-1)`.
    201199
    202200           * For more information on the different encodings, see the
    203              :mod:`pseudolimes module <sage.geometry.pseudolines>`'s
     201             :mod:`pseudolines module <sage.geometry.pseudolines>`'s
    204202             documentation.
    205    
     203
    206204        TESTS:
    207205
    208206        From permutations::
    209    
    210             sage: from sage.geometry.pseudolines import PseudolinesArrangement
     207
     208            sage: from sage.geometry.pseudolines import PseudolineArrangement
    211209            sage: permutations = [[3, 2, 1], [3, 2, 0], [3, 1, 0], [2, 1, 0]]
    212             sage: PseudolinesArrangement(permutations)
     210            sage: PseudolineArrangement(permutations)
    213211            Arrangement of pseudolines of size 4
    214212
    215213        From transpositions ::
    216214
    217             sage: from sage.geometry.pseudolines import PseudolinesArrangement
     215            sage: from sage.geometry.pseudolines import PseudolineArrangement
    218216            sage: transpositions = [(3, 2), (3, 1), (0, 3), (2, 1), (0, 2), (0, 1)]
    219             sage: PseudolinesArrangement(transpositions)
     217            sage: PseudolineArrangement(transpositions)
    220218            Arrangement of pseudolines of size 4
    221219
    222220        From a Felsner matrix::
    223221
    224             sage: from sage.geometry.pseudolines import PseudolinesArrangement
     222            sage: from sage.geometry.pseudolines import PseudolineArrangement
    225223            sage: permutations = [[3, 2, 1], [3, 2, 0], [3, 1, 0], [2, 1, 0]]
    226             sage: p = PseudolinesArrangement(permutations)
     224            sage: p = PseudolineArrangement(permutations)
    227225            sage: matrix = p.felsner_matrix()
    228             sage: PseudolinesArrangement(matrix) == p
     226            sage: PseudolineArrangement(matrix) == p
    229227            True
    230228
    231229        TESTS:
    232230
    233231        Wrong input::
    234232
    235             sage: PseudolinesArrangement([[5, 2, 1], [3, 2, 0], [3, 1, 0], [2, 1, 0]])
     233            sage: PseudolineArrangement([[5, 2, 1], [3, 2, 0], [3, 1, 0], [2, 1, 0]])
    236234            Traceback (most recent call last):
    237235            ...
    238             ValueError: Are the lines really numbered from 0 to n-1 ?
    239             sage: PseudolinesArrangement([(3, 2), (3, 1), (0, 3), (2, 1), (0, 2)])
     236            ValueError: Are the lines really numbered from 0 to n-1?
     237            sage: PseudolineArrangement([(3, 2), (3, 1), (0, 3), (2, 1), (0, 2)])
    240238            Traceback (most recent call last):
    241239            ...
    242             ValueError: A line is numbered with 3but the number of transpositions ...
     240            ValueError: A line is numbered 3 but the number of transpositions ...
    243241        """
    244        
     242
    245243        # Sequence of transpositions
    246         if (encoding == "transpositions" or 
     244        if (encoding == "transpositions" or
    247245            (encoding == "auto" and len(seq[0]) == 2 and len(seq) > 3)):
    248            
    249             self._n = max(map(max, seq)) + 1 
     246
     247            self._n = max(map(max, seq)) + 1
    250248            if (self._n * (self._n-1))/2 != len(seq):
    251249                raise ValueError(
    252                     "A line is numbered with "+str(self._n-1)+"but the number "+
    253                     "of transpositions is different from binomial("+
    254                     str(self._n-1)+",2). Are the lines numbered from 0 to n-1 ?"+
    255                     "Are they really non-parallel ? Please check the documentation.")
     250                    "A line is numbered "+str(self._n-1)+" but the number"+
     251                    " of transpositions is different from binomial("+
     252                    str(self._n-1)+",2). Are the lines numbered from 0 to n-1?"+
     253                    " Are they really non-parallel? Please check the documentation.")
    256254
    257255            self._permutations = [[] for i in range(self._n)]
    258256
     
    261259                self._permutations[j].append(i)
    262260
    263261        # Sequence of permutations
    264         elif (encoding == "permutations" or 
     262        elif (encoding == "permutations" or
    265263            (encoding == "auto" and (len(seq[0]) == len(seq)-1) and max(seq[0]) > 1)):
    266            
     264
    267265            self._n = len(seq)
    268266            self._permutations = deepcopy(seq)
    269267
    270268            if max(map(max, seq)) != self._n -1 :
    271                 raise ValueError("Are the lines really numbered from 0 to n-1 ?")
     269                raise ValueError("Are the lines really numbered from 0 to n-1?")
    272270
    273271        # Felsner encoding
    274         elif (encoding == "Felsner" or 
     272        elif (encoding == "Felsner" or
    275273            (encoding == "auto" and len(seq[0]) == len(seq) -1)):
    276274
    277275            seq = deepcopy(seq)
     
    289287                     seq[i+1][0] == 1)):
    290288
    291289                    crossings -= 1
    292                    
     290
    293291                    self._permutations[ordering[i]].append(ordering[i+1])
    294292                    self._permutations[ordering[i+1]].append(ordering[i])
    295293
    296294                    ordering[i], ordering[i+1] = ordering[i+1], ordering[i]
    297295                    seq[i], seq[i+1] = seq[i+1], seq[i]
    298                    
     296
    299297                    seq[i].pop(0)
    300298                    seq[i+1].pop(0)
    301299
    302300                    if i > 0 and seq[i-1] is not []:
    303301                        i -= 1
    304                     elif seq[i] is not []:
    305                         i += 1
     302                    else:
     303                        i += 1 
    306304                else:
    307305                    i += 1
    308306        else:
     
    310308            if encoding != "auto":
    311309                raise ValueError("The value of encoding must be one of 'transpositions', 'permutations', 'Felsner' or 'auto'.")
    312310
    313             raise ValueError("The encoding you use could not be guessed. Your input string is probably badly formatted, or you have less than 3 lines and we can make no diffence between the encoding. Please specify the encoding you used.")
     311            raise ValueError("The encoding you used could not be guessed. Your input string is probably badly formatted, or you have at most 3 lines and we cannot distinguish the encoding. Please specify the encoding you used.")
    314312
    315313    def transpositions(self):
    316314        r"""
    317315        Returns the arrangement as `\binom n 2` transpositions.
    318316
    319         See the :mod:`pseudolimes module <sage.geometry.pseudolines>`'s
     317        See the :mod:`pseudolines module <sage.geometry.pseudolines>`'s
    320318        documentation for more information on this encoding.
    321319
    322320        EXAMPLE::
    323321
    324             sage: from sage.geometry.pseudolines import PseudolinesArrangement
     322            sage: from sage.geometry.pseudolines import PseudolineArrangement
    325323            sage: permutations = [[3, 2, 1], [3, 2, 0], [3, 1, 0], [2, 1, 0]]
    326             sage: p1 = PseudolinesArrangement(permutations)
     324            sage: p1 = PseudolineArrangement(permutations)
    327325            sage: transpositions = [(3, 2), (3, 1), (0, 3), (2, 1), (0, 2), (0, 1)]
    328             sage: p2 = PseudolinesArrangement(transpositions)
     326            sage: p2 = PseudolineArrangement(transpositions)
    329327            sage: p1 == p2
    330328            True
    331329            sage: p1.transpositions()
     
    366364
    367365        if max(map(len,perm)) != 0:
    368366            raise ValueError("There has been an error while computing the transpositions.")
    369            
     367
    370368        return t
    371369
    372370    def permutations(self):
    373371        r"""
    374372        Returns the arrangements as `n` permutations of size `n-1`.
    375373
    376         See the :mod:`pseudolimes module <sage.geometry.pseudolines>`'s
     374        See the :mod:`pseudolines module <sage.geometry.pseudolines>`'s
    377375        documentation for more information on this encoding.
    378376
    379377        EXAMPLE::
    380378
    381             sage: from sage.geometry.pseudolines import PseudolinesArrangement
     379            sage: from sage.geometry.pseudolines import PseudolineArrangement
    382380            sage: permutations = [[3, 2, 1], [3, 2, 0], [3, 1, 0], [2, 1, 0]]
    383             sage: p = PseudolinesArrangement(permutations)
     381            sage: p = PseudolineArrangement(permutations)
    384382            sage: p.permutations()
    385383            [[3, 2, 1], [3, 2, 0], [3, 1, 0], [2, 1, 0]]
    386384        """
     
    390388        r"""
    391389        Returns a Felsner matrix describing the arrangement.
    392390
    393         See the :mod:`pseudolimes module <sage.geometry.pseudolines>`'s
     391        See the :mod:`pseudolines module <sage.geometry.pseudolines>`'s
    394392        documentation for more information on this encoding.
    395393
    396394        EXAMPLE::
    397395
    398             sage: from sage.geometry.pseudolines import PseudolinesArrangement
     396            sage: from sage.geometry.pseudolines import PseudolineArrangement
    399397            sage: permutations = [[3, 2, 1], [3, 2, 0], [3, 1, 0], [2, 1, 0]]
    400             sage: p = PseudolinesArrangement(permutations)
     398            sage: p = PseudolineArrangement(permutations)
    401399            sage: p.felsner_matrix()
    402400            [[0, 0, 0], [0, 0, 1], [0, 1, 1], [1, 1, 1]]
    403401        """
     
    417415        r"""
    418416        Displays the pseudoline arrangement as a wiring diagram.
    419417
    420         INPUT: 
     418        INPUT:
    421419
    422420        - ``**args`` -- any arguments to be forwarded to the ``show`` method. In
    423421          particular, to tune the dimensions, use the ``figsize`` argument
     
    425423
    426424        EXAMPLE::
    427425
    428             sage: from sage.geometry.pseudolines import PseudolinesArrangement
     426            sage: from sage.geometry.pseudolines import PseudolineArrangement
    429427            sage: permutations = [[3, 2, 1], [3, 2, 0], [3, 1, 0], [2, 1, 0]]
    430             sage: p = PseudolinesArrangement(permutations)
     428            sage: p = PseudolineArrangement(permutations)
    431429            sage: p.show(figsize=[7,5])
    432430
    433431        TESTS::
    434432
    435             sage: from sage.geometry.pseudolines import PseudolinesArrangement
     433            sage: from sage.geometry.pseudolines import PseudolineArrangement
    436434            sage: permutations = [[3, 2, 1], [3, 2, 0], [3, 0, 1], [2, 0, 1]]
    437             sage: p = PseudolinesArrangement(permutations)
     435            sage: p = PseudolineArrangement(permutations)
    438436            sage: p.show()
    439437            Traceback (most recent call last):
    440438            ...
     
    464462            lines[j].append((x+2,iy))
    465463
    466464            x += 2
    467                            
     465
    468466        L = line([(1,1)])
    469        
     467
    470468        for i, l in enumerate(lines):
    471469            l.append((x+2, l[-1][1]))
    472470            L += line(l)
    473            
    474             L += text(str(i), (0, l[0][1]+.3))
    475             L += text(str(i), (x+2, l[-1][1]+.3))
     471
     472            L += text(str(i), (0, l[0][1]+.3), horizontal_alignment="right")
     473            L += text(str(i), (x+2, l[-1][1]+.3), horizontal_alignment="left")
    476474
    477475        return L.show(axes = False, **args)
    478            
     476
    479477
    480478    def __repr__(self):
    481479        r"""
    482         A short txt description of the pseudolines arrangement.
     480        A short txt description of the pseudoline arrangement.
    483481
    484482        EXAMPLE::
    485483
    486             sage: from sage.geometry.pseudolines import PseudolinesArrangement
     484            sage: from sage.geometry.pseudolines import PseudolineArrangement
    487485            sage: permutations = [[3, 2, 1], [3, 2, 0], [3, 1, 0], [2, 1, 0]]
    488             sage: p = PseudolinesArrangement(permutations)
     486            sage: p = PseudolineArrangement(permutations)
    489487            sage: p
    490488            Arrangement of pseudolines of size 4
    491489        """
     
    497495
    498496        TEST::
    499497
    500             sage: from sage.geometry.pseudolines import PseudolinesArrangement
     498            sage: from sage.geometry.pseudolines import PseudolineArrangement
    501499            sage: permutations = [[3, 2, 1], [3, 2, 0], [3, 1, 0], [2, 1, 0]]
    502             sage: p1 = PseudolinesArrangement(permutations)
     500            sage: p1 = PseudolineArrangement(permutations)
    503501            sage: transpositions = [(3, 2), (3, 1), (0, 3), (2, 1), (0, 2), (0, 1)]
    504             sage: p2 = PseudolinesArrangement(transpositions)
     502            sage: p2 = PseudolineArrangement(transpositions)
    505503            sage: p1 == p2
    506             True       
     504            True
    507505        """
    508506        return (self._n == other._n) and (self._permutations == other._permutations)