Ticket #14319: trac_14319_fix_fan_isomorphism.patch

File trac_14319_fix_fan_isomorphism.patch, 6.6 KB (added by vbraun, 8 years ago)

Updated patch

  • sage/geometry/fan.py

    # HG changeset patch
    # User Volker Braun <vbraun.name@gmail.com>
    # Date 1364850253 -3600
    # Node ID 03a0e1541df6264eec5320e8f5c8e6c983707c8c
    # Parent  a79a31a3136ca71ab2ad35a0ce89d75a2eeae93a
    Fix bug in fan isomorphism check and improve doctesting
    
    diff --git a/sage/geometry/fan.py b/sage/geometry/fan.py
    a b  
    26832683
    26842684        EXAMPLES::
    26852685
    2686             sage: rays = ((1, 1), (0, 1), (-1, -1), (1, 0))
     2686            sage: rays = ((1, 1), (0, 1), (-1, -1), (3, 1))
    26872687            sage: cones = [(0,1), (1,2), (2,3), (3,0)]
    26882688            sage: fan1 = Fan(cones, rays)
    26892689            sage: m = matrix([[-2,3],[1,-1]])
  • sage/geometry/fan_isomorphism.py

    diff --git a/sage/geometry/fan_isomorphism.py b/sage/geometry/fan_isomorphism.py
    a b  
    1616
    1717from sage.rings.all import ZZ
    1818from sage.matrix.constructor import column_matrix, matrix
     19from sage.geometry.cone import Cone
    1920
    2021
    2122
     
    7677
    7778    OUTPUT:
    7879
    79     Yields the fan isomorphisms as matrices.
     80    Yields the fan isomorphisms as matrices acting from the right on
     81    rays.
    8082
    8183    EXAMPLES::
    8284
     
    8486        sage: from sage.geometry.fan_isomorphism import fan_isomorphism_generator
    8587        sage: tuple( fan_isomorphism_generator(fan, fan) )
    8688        (
    87         [1 0]  [ 1  0]  [0 1]  [ 0  1]  [-1 -1]  [-1 -1]
    88         [0 1], [-1 -1], [1 0], [-1 -1], [ 1  0], [ 0  1]
     89        [1 0]  [0 1]  [ 1  0]  [-1 -1]  [ 0  1]  [-1 -1]
     90        [0 1], [1 0], [-1 -1], [ 1  0], [-1 -1], [ 0  1]
    8991        )
    9092
    9193        sage: m1 = matrix([(1, 0), (0, -5), (-3, 4)])
     
    100102        [18  1 -5]
    101103        [ 4  0 -1]
    102104        [ 5  0 -1]
     105
     106        sage: m0 = identity_matrix(ZZ, 2)
     107        sage: m1 = matrix([(1, 0), (0, -5), (-3, 4)])
     108        sage: m2 = matrix([(3, 0), (1, 0), (-2, 1)])
     109        sage: m1.elementary_divisors() == m2.elementary_divisors() == [1,1,0]
     110        True
     111        sage: fan0 = Fan([Cone([m0*vector([1,0]), m0*vector([1,1])]),
     112        ...               Cone([m0*vector([1,1]), m0*vector([0,1])])])
     113        sage: fan1 = Fan([Cone([m1*vector([1,0]), m1*vector([1,1])]),
     114        ...               Cone([m1*vector([1,1]), m1*vector([0,1])])])
     115        sage: fan2 = Fan([Cone([m2*vector([1,0]), m2*vector([1,1])]),
     116        ...               Cone([m2*vector([1,1]), m2*vector([0,1])])])
     117        sage: tuple(fan_isomorphism_generator(fan0, fan0))
     118        (
     119        [1 0]  [0 1]
     120        [0 1], [1 0]
     121        )
     122        sage: tuple(fan_isomorphism_generator(fan1, fan1))
     123        (
     124        [1 0 0]  [ -3 -20  28]
     125        [0 1 0]  [ -1  -4   7]
     126        [0 0 1], [ -1  -5   8]
     127        )
     128        sage: tuple(fan_isomorphism_generator(fan1, fan2))
     129        (
     130        [18  1 -5]  [ 6 -3  7]
     131        [ 4  0 -1]  [ 1 -1  2]
     132        [ 5  0 -1], [ 2 -1  2]
     133        )
     134        sage: tuple(fan_isomorphism_generator(fan2, fan1))                 
     135        (
     136        [ 0 -1  1]  [ 0 -1  1]
     137        [ 1 -7  2]  [ 2 -2 -5]
     138        [ 0 -5  4], [ 1  0 -3]
     139        )
    103140    """
    104141    if not fan_isomorphic_necessary_conditions(fan1, fan2):
    105142        return
     
    109146    graph_iso = graph1.is_isomorphic(graph2, edge_labels=True, certify=True)
    110147    if not graph_iso[0]:
    111148        return
    112     graph_iso = dict( (k.ray(0), v.ambient_ray_indices()[0])
    113                       for k,v in graph_iso[1].iteritems() )
     149    graph_iso = graph_iso[1]
    114150
     151    # Pick a basis of rays in fan1
    115152    max_cone = fan1(fan1.dim())[0]
    116153    fan1_pivot_rays = max_cone.rays()
    117154    fan1_basis = fan1_pivot_rays + fan1.virtual_rays()   # A QQ-basis for N_1
     155    fan1_pivot_cones = [ fan1.embed(Cone([r])) for r in fan1_pivot_rays ]
    118156
    119     # The fan2 cones as set(set(integers))
     157    # The fan2 cones as set(set(ray indices))
    120158    fan2_cones = frozenset(
    121159        frozenset(cone.ambient_ray_indices())
    122160        for cone in fan2.generating_cones() )
    123161
    124162    # iterate over all graph isomorphisms graph1 -> graph2
    125     g2 = graph2.relabel({v:(i if i!=0 else graph2.order()) for i,v in enumerate(graph2.vertices())}, inplace = False)
    126 
    127     for perm in g2.automorphism_group(edge_labels=True):
    128         # find a candidate m that maps max_cone to the graph image cone
    129         image_ray_indices = [ perm(graph_iso[r]+1)-1 for r in fan1_pivot_rays ]
    130         fan2_basis = fan2.rays(image_ray_indices) + fan2.virtual_rays()
     163    for perm in graph2.automorphism_group(edge_labels=True):
     164        # find a candidate m that maps fan1_basis to the image rays under the graph isomorphism
     165        fan2_pivot_cones = [ perm(graph_iso[c]) for c in fan1_pivot_cones ]
     166        fan2_pivot_rays = fan2.rays([ c.ambient_ray_indices()[0] for c in fan2_pivot_cones  ])
     167        fan2_basis = fan2_pivot_rays + fan2.virtual_rays()
    131168        try:
    132             m = matrix(fan1_basis).solve_right(matrix(fan2_basis))
     169            m = matrix(ZZ, fan1_basis).solve_right(matrix(ZZ, fan2_basis))
    133170            m = m.change_ring(ZZ)
    134171        except (ValueError, TypeError):
    135172            continue # no solution
    136173
    137174        # check that the candidate m lifts the vertex graph homomorphism
    138         graph_image_ray_indices = [ perm(graph_iso[r]+1)-1 for r in fan1.rays() ]
     175        graph_image_ray_indices = [ perm(graph_iso[c]).ambient_ray_indices()[0] for c in fan1(1) ]
    139176        try:
    140             matrix_image_ray_indices = [ fan2.rays().index(fan1.ray(i)*m)
    141                                          for i in range(fan1.nrays()) ]
     177            matrix_image_ray_indices = [ fan2.rays().index(r*m) for r in fan1.rays() ]
    142178        except ValueError:
    143179            continue
    144180        if graph_image_ray_indices != matrix_image_ray_indices:
     
    150186                      for i in cone.ambient_ray_indices())
    151187            for cone in fan1.generating_cones() )
    152188        if image_cones == fan2_cones:
     189            m.set_immutable()
    153190            yield m
    154191
    155192
     
    172209
    173210    EXAMPLE::
    174211
    175         sage: rays = ((1, 1), (0, 1), (-1, -1), (1, 0))
     212        sage: rays = ((1, 1), (0, 1), (-1, -1), (3, 1))
    176213        sage: cones = [(0,1), (1,2), (2,3), (3,0)]
    177214        sage: fan1 = Fan(cones, rays)
    178215
     
    193230        Traceback (most recent call last):
    194231        ...
    195232        FanNotIsomorphicError
     233
     234        sage: fan1 = Fan(cones=[[1,3,4,5],[0,1,2,3],[2,3,4],[0,1,5]],
     235        ...              rays=[(-1,-1,0),(-1,-1,3),(-1,1,-1),(-1,3,-1),(0,2,-1),(1,-1,1)])
     236        sage: fan2 = Fan(cones=[[0,2,3,5],[0,1,4,5],[0,1,2],[3,4,5]],
     237        ...              rays=[(-1,-1,-1),(-1,-1,0),(-1,1,-1),(0,2,-1),(1,-1,1),(3,-1,-1)])
     238        sage: fan1.is_isomorphic(fan2)
     239        True
    196240    """
    197241    generator = fan_isomorphism_generator(fan1, fan2)
    198242    try: