|
41 | 41 | # (at your option) any later version. |
42 | 42 | # https://www.gnu.org/licenses/ |
43 | 43 | # **************************************************************************** |
44 | | -import itertools |
45 | | - |
46 | 44 | from copy import copy |
47 | 45 | from itertools import combinations |
| 46 | +from typing import Any |
48 | 47 |
|
49 | 48 | from sage.combinat.permutation import Permutation |
50 | 49 | from sage.functions.generalized import sign |
|
71 | 70 |
|
72 | 71 | lazy_import('sage.libs.braiding', ['leftnormalform', 'rightnormalform']) |
73 | 72 |
|
74 | | -roots_interval_cache = {} |
| 73 | +roots_interval_cache: dict[tuple, Any] = {} |
75 | 74 |
|
76 | 75 |
|
77 | 76 | def braid_from_piecewise(strands): |
@@ -109,8 +108,8 @@ def braid_from_piecewise(strands): |
109 | 108 | yauxi = val[indices[j]][2] |
110 | 109 | aaux = val[indices[j] - 1][0] |
111 | 110 | baux = val[indices[j]][0] |
112 | | - interpolar = xauxr + (yauxr - xauxr)*(i - aaux) / (baux - aaux) |
113 | | - interpolai = xauxi + (yauxi - xauxi)*(i - aaux) / (baux - aaux) |
| 111 | + interpolar = xauxr + (yauxr - xauxr) * (i - aaux) / (baux - aaux) |
| 112 | + interpolai = xauxi + (yauxi - xauxi) * (i - aaux) / (baux - aaux) |
114 | 113 | totalpoints[j].append([interpolar, interpolai]) |
115 | 114 | else: |
116 | 115 | totalpoints[j].append([val[indices[j]][1], |
@@ -219,9 +218,10 @@ def discrim_pairs(f, g): |
219 | 218 |
|
220 | 219 |
|
221 | 220 | @cached_function |
222 | | -def corrected_voronoi_diagram(points): |
| 221 | +def corrected_voronoi_diagram(points) -> VoronoiDiagram: |
223 | 222 | r""" |
224 | 223 | Compute a Voronoi diagram of a set of points with rational coordinates. |
| 224 | +
|
225 | 225 | The given points are granted to lie one in each bounded region. |
226 | 226 |
|
227 | 227 | INPUT: |
@@ -276,7 +276,7 @@ def corrected_voronoi_diagram(points): |
276 | 276 | return V |
277 | 277 |
|
278 | 278 |
|
279 | | -def orient_circuit(circuit, convex=False, precision=53, verbose=False): |
| 279 | +def orient_circuit(circuit, convex=False, precision=53, verbose=False) -> tuple: |
280 | 280 | r""" |
281 | 281 | Reverse a circuit if it goes clockwise; otherwise leave it unchanged. |
282 | 282 |
|
@@ -331,7 +331,7 @@ def orient_circuit(circuit, convex=False, precision=53, verbose=False): |
331 | 331 | sage: cir_oriented == orient_circuit(cir, convex=True) |
332 | 332 | True |
333 | 333 | sage: P0=[(1,1/2),(0,1),(1,1)]; P1=[(0,3/2),(-1,0)] |
334 | | - sage: Q=Polyhedron(P0).vertices() |
| 334 | + sage: Q = Polyhedron(P0).vertices() |
335 | 335 | sage: Q = [Q[2], Q[0], Q[1]] + [_ for _ in reversed(Polyhedron(P1).vertices())] |
336 | 336 | sage: Q |
337 | 337 | [A vertex at (1, 1/2), A vertex at (0, 1), A vertex at (1, 1), |
@@ -369,7 +369,7 @@ def orient_circuit(circuit, convex=False, precision=53, verbose=False): |
369 | 369 | print(prec) |
370 | 370 |
|
371 | 371 |
|
372 | | -def voronoi_cells(V, vertical_lines=frozenset()): |
| 372 | +def voronoi_cells(V, vertical_lines=frozenset()) -> tuple: |
373 | 373 | r""" |
374 | 374 | Compute the graph, the boundary graph, a base point, a positive orientation |
375 | 375 | of the boundary graph, and the dual graph of a corrected Voronoi diagram. |
@@ -480,7 +480,7 @@ def voronoi_cells(V, vertical_lines=frozenset()): |
480 | 480 | return (G, E, p, EC, DG, vertical_regions) |
481 | 481 |
|
482 | 482 |
|
483 | | -def followstrand(f, factors, x0, x1, y0a, prec=53) -> list: |
| 483 | +def followstrand(f, factors, x0, x1, y0a, prec=53) -> list[tuple]: |
484 | 484 | r""" |
485 | 485 | Return a piecewise linear approximation of the homotopy continuation |
486 | 486 | of the root ``y0a`` from ``x0`` to ``x1``. |
@@ -564,18 +564,18 @@ def followstrand(f, factors, x0, x1, y0a, prec=53) -> list: |
564 | 564 | ci = c.imag() |
565 | 565 | coefsfactors += list(cr.endpoints()) |
566 | 566 | coefsfactors += list(ci.endpoints()) |
567 | | - from sage.libs.sirocco import (contpath, contpath_mp, contpath_comps, contpath_mp_comps) |
| 567 | + from sage.libs.sirocco import (contpath, contpath_mp, |
| 568 | + contpath_comps, contpath_mp_comps) |
568 | 569 | try: |
569 | 570 | if prec == 53: |
570 | 571 | if factors: |
571 | 572 | points = contpath_comps(deg, coefs, yr, yi, degsfactors, coefsfactors) |
572 | 573 | else: |
573 | 574 | points = contpath(deg, coefs, yr, yi) |
| 575 | + elif factors: |
| 576 | + points = contpath_mp_comps(deg, coefs, yr, yi, prec, degsfactors, coefsfactors) |
574 | 577 | else: |
575 | | - if factors: |
576 | | - points = contpath_mp_comps(deg, coefs, yr, yi, prec, degsfactors, coefsfactors) |
577 | | - else: |
578 | | - points = contpath_mp(deg, coefs, yr, yi, prec) |
| 578 | + points = contpath_mp(deg, coefs, yr, yi, prec) |
579 | 579 | return points |
580 | 580 | except Exception: |
581 | 581 | return followstrand(f, factors, x0, x1, y0a, 2 * prec) |
@@ -613,7 +613,7 @@ def newton(f, x0, i0): |
613 | 613 | return x0 - f(x0) / f.derivative()(i0) |
614 | 614 |
|
615 | 615 |
|
616 | | -def fieldI(field): |
| 616 | +def fieldI(field: NumberField) -> NumberField: |
617 | 617 | r""" |
618 | 618 | Return the (either double or trivial) extension of a number field which contains ``I``. |
619 | 619 |
|
@@ -675,7 +675,7 @@ def fieldI(field): |
675 | 675 |
|
676 | 676 |
|
677 | 677 | @parallel |
678 | | -def roots_interval(f, x0): |
| 678 | +def roots_interval(f, x0) -> dict: |
679 | 679 | """ |
680 | 680 | Find disjoint intervals that isolate the roots of a polynomial for a fixed |
681 | 681 | value of the first variable. |
@@ -747,7 +747,7 @@ def roots_interval(f, x0): |
747 | 747 | return result |
748 | 748 |
|
749 | 749 |
|
750 | | -def roots_interval_cached(f, x0): |
| 750 | +def roots_interval_cached(f, x0) -> dict: |
751 | 751 | r""" |
752 | 752 | Cached version of :func:`roots_interval`. |
753 | 753 |
|
@@ -777,7 +777,7 @@ def roots_interval_cached(f, x0): |
777 | 777 | return result |
778 | 778 |
|
779 | 779 |
|
780 | | -def populate_roots_interval_cache(inputs): |
| 780 | +def populate_roots_interval_cache(inputs) -> None: |
781 | 781 | r""" |
782 | 782 | Call :func:`roots_interval` to the inputs that have not been |
783 | 783 | computed previously, and cache them. |
@@ -889,7 +889,7 @@ def braid_in_segment(glist, x0, x1, precision={}): |
889 | 889 | CIFp = ComplexIntervalField(precision1[f]) |
890 | 890 | intervals[f] = [r.interval(CIFp) for r in y0sf] |
891 | 891 | if not any(a.overlaps(b) for a, b in |
892 | | - itertools.combinations(intervals[f], 2)): |
| 892 | + combinations(intervals[f], 2)): |
893 | 893 | break |
894 | 894 | precision1[f] *= 2 |
895 | 895 | strands = [] |
@@ -934,7 +934,8 @@ def braid_in_segment(glist, x0, x1, precision={}): |
934 | 934 | return initialbraid * centralbraid * finalbraid |
935 | 935 |
|
936 | 936 |
|
937 | | -def geometric_basis(G, E, EC0, p, dual_graph, vertical_regions={}) -> list: |
| 937 | +def geometric_basis(G, E, EC0, p, dual_graph, |
| 938 | + vertical_regions={}) -> tuple[list, dict]: |
938 | 939 | r""" |
939 | 940 | Return a geometric basis, based on a vertex. |
940 | 941 |
|
@@ -1122,7 +1123,7 @@ def geometric_basis(G, E, EC0, p, dual_graph, vertical_regions={}) -> list: |
1122 | 1123 | return (resul, vd) |
1123 | 1124 |
|
1124 | 1125 |
|
1125 | | -def vertical_lines_in_braidmon(pols) -> list: |
| 1126 | +def vertical_lines_in_braidmon(pols) -> list[int]: |
1126 | 1127 | r""" |
1127 | 1128 | Return the vertical lines in ``pols``, unless |
1128 | 1129 | one of the other components has a vertical asymptote. |
@@ -1164,7 +1165,7 @@ def vertical_lines_in_braidmon(pols) -> list: |
1164 | 1165 | return res |
1165 | 1166 |
|
1166 | 1167 |
|
1167 | | -def strand_components(f, pols, p1): |
| 1168 | +def strand_components(f, pols, p1) -> tuple[list, dict]: |
1168 | 1169 | r""" |
1169 | 1170 | Compute only the assignment from strands to elements of ``flist``. |
1170 | 1171 |
|
@@ -1210,7 +1211,7 @@ def strand_components(f, pols, p1): |
1210 | 1211 | return (roots_base, strands) |
1211 | 1212 |
|
1212 | 1213 |
|
1213 | | -def braid_monodromy(f, arrangement=(), vertical=False): |
| 1214 | +def braid_monodromy(f, arrangement=(), vertical=False) -> tuple: |
1214 | 1215 | r""" |
1215 | 1216 | Compute the braid monodromy of a projection of the curve defined by |
1216 | 1217 | a polynomial. |
@@ -1308,22 +1309,19 @@ def braid_monodromy(f, arrangement=(), vertical=False): |
1308 | 1309 | arrangement_h = tuple(f1.subs({x: x + y}) for f1 in arrangement_h) |
1309 | 1310 | arrangement1 = arrangement_h |
1310 | 1311 | glist = tuple(f1.subs({x: x + y}) for f1 in glist) |
1311 | | - if d > 0: |
1312 | | - disc = discrim(glist) |
1313 | | - else: |
1314 | | - disc = [] |
| 1312 | + disc = discrim(glist) if d > 0 else [] |
1315 | 1313 | vertical_braid = {} |
1316 | 1314 | transversal = {} |
1317 | | - vl = [] |
| 1315 | + vl_list = [] |
1318 | 1316 | for f0 in arrangement_v: |
1319 | 1317 | pt = [j for j, t in enumerate(disc) if f0.subs({x: t}) == 0] |
1320 | 1318 | if pt: |
1321 | 1319 | vertical_braid[f0] = (pt[0], arrangement1.index(f0)) |
1322 | | - vl.append(pt[0]) |
| 1320 | + vl_list.append(pt[0]) |
1323 | 1321 | else: |
1324 | 1322 | transversal[f0] = arrangement1.index(f0) |
1325 | | - vl.sort() |
1326 | | - vl = frozenset(vl) |
| 1323 | + vl_list.sort() |
| 1324 | + vl = frozenset(vl_list) |
1327 | 1325 | if not disc: |
1328 | 1326 | vertical_braids = {i: transversal[f0] |
1329 | 1327 | for i, f0 in enumerate(transversal)} |
@@ -1354,13 +1352,13 @@ def braid_monodromy(f, arrangement=(), vertical=False): |
1354 | 1352 | k = arrangement1.index(arrangement_h[i]) |
1355 | 1353 | strands1[j] = k |
1356 | 1354 | geombasis, vd = geometric_basis(G, E, EC, p, DG, vertical_regions=VR) |
1357 | | - segs = set() |
| 1355 | + segs_set = set() |
1358 | 1356 | for p in geombasis: |
1359 | | - for s in zip(p[:-1], p[1:]): |
1360 | | - if (s[1], s[0]) not in segs: |
1361 | | - segs.add((s[0], s[1])) |
| 1357 | + for s0, s1 in zip(p[:-1], p[1:]): |
| 1358 | + if (s1, s0) not in segs_set: |
| 1359 | + segs_set.add((s0, s1)) |
1362 | 1360 | I0 = QQbar.gen() |
1363 | | - segs = [(a[0] + I0 * a[1], b[0] + I0 * b[1]) for a, b in segs] |
| 1361 | + segs = [(a[0] + I0 * a[1], b[0] + I0 * b[1]) for a, b in segs_set] |
1364 | 1362 | vertices = list(set(flatten(segs))) |
1365 | 1363 | tocacheverts = tuple([(g, v) for v in vertices]) |
1366 | 1364 | populate_roots_interval_cache(tocacheverts) |
@@ -1403,7 +1401,7 @@ def braid_monodromy(f, arrangement=(), vertical=False): |
1403 | 1401 | return (result, strands1, vertical_braids, d) |
1404 | 1402 |
|
1405 | 1403 |
|
1406 | | -def conjugate_positive_form(braid): |
| 1404 | +def conjugate_positive_form(braid) -> list[list]: |
1407 | 1405 | r""" |
1408 | 1406 | For a ``braid`` which is conjugate to a product of *disjoint* positive |
1409 | 1407 | braids a list of such decompositions is given. |
@@ -1485,13 +1483,14 @@ def conjugate_positive_form_p(braid): |
1485 | 1483 | return conjugate_positive_form(braid) |
1486 | 1484 |
|
1487 | 1485 |
|
1488 | | -def braid2rels(L): |
| 1486 | +def braid2rels(L) -> list: |
1489 | 1487 | r""" |
1490 | 1488 | Return a minimal set of relations of the group |
1491 | 1489 | ``F / [(b * F([j])) / F([j]) for j in (1..d)]`` where ``F = FreeGroup(d)`` |
1492 | | - and ``b`` is a conjugate of a positive braid . One starts from the |
1493 | | - non-trivial relations determined by the positive braid and transform |
1494 | | - them in relations determined by ``b``. |
| 1490 | + and ``b`` is a conjugate of a positive braid. |
| 1491 | +
|
| 1492 | + One starts from the non-trivial relations determined by the |
| 1493 | + positive braid and transform them in relations determined by ``b``. |
1495 | 1494 |
|
1496 | 1495 | INPUT: |
1497 | 1496 |
|
@@ -1813,7 +1812,7 @@ def fundamental_group_arrangement(flist, simplified=True, projective=False, |
1813 | 1812 | OUTPUT: |
1814 | 1813 |
|
1815 | 1814 | - A list of braids. The braids correspond to paths based in the same point; |
1816 | | - each of this paths is the conjugated of a loop around one of the points |
| 1815 | + each of these paths is the conjugated of a loop around one of the points |
1817 | 1816 | in the discriminant of the projection of ``f``. |
1818 | 1817 |
|
1819 | 1818 | - A dictionary attaching to ``j`` a tuple a list of elements |
@@ -1880,7 +1879,7 @@ def fundamental_group_arrangement(flist, simplified=True, projective=False, |
1880 | 1879 | R = f.parent() |
1881 | 1880 | else: |
1882 | 1881 | R = PolynomialRing(QQ, ('x', 'y')) |
1883 | | - f = R(1) |
| 1882 | + f = R.one() |
1884 | 1883 | x, y = R.gens() |
1885 | 1884 | flist1 = tuple(flist) |
1886 | 1885 | if vertical and vertical_lines_in_braidmon(flist1): |
|
0 commit comments