Ticket #14319: trac_14319_fix_fan_isomorphism.patch
File trac_14319_fix_fan_isomorphism.patch, 6.6 KB (added by , 8 years ago) 


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 2683 2683 2684 2684 EXAMPLES:: 2685 2685 2686 sage: rays = ((1, 1), (0, 1), (1, 1), ( 1, 0))2686 sage: rays = ((1, 1), (0, 1), (1, 1), (3, 1)) 2687 2687 sage: cones = [(0,1), (1,2), (2,3), (3,0)] 2688 2688 sage: fan1 = Fan(cones, rays) 2689 2689 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 16 16 17 17 from sage.rings.all import ZZ 18 18 from sage.matrix.constructor import column_matrix, matrix 19 from sage.geometry.cone import Cone 19 20 20 21 21 22 … … 76 77 77 78 OUTPUT: 78 79 79 Yields the fan isomorphisms as matrices. 80 Yields the fan isomorphisms as matrices acting from the right on 81 rays. 80 82 81 83 EXAMPLES:: 82 84 … … 84 86 sage: from sage.geometry.fan_isomorphism import fan_isomorphism_generator 85 87 sage: tuple( fan_isomorphism_generator(fan, fan) ) 86 88 ( 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] 89 91 ) 90 92 91 93 sage: m1 = matrix([(1, 0), (0, 5), (3, 4)]) … … 100 102 [18 1 5] 101 103 [ 4 0 1] 102 104 [ 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 ) 103 140 """ 104 141 if not fan_isomorphic_necessary_conditions(fan1, fan2): 105 142 return … … 109 146 graph_iso = graph1.is_isomorphic(graph2, edge_labels=True, certify=True) 110 147 if not graph_iso[0]: 111 148 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] 114 150 151 # Pick a basis of rays in fan1 115 152 max_cone = fan1(fan1.dim())[0] 116 153 fan1_pivot_rays = max_cone.rays() 117 154 fan1_basis = fan1_pivot_rays + fan1.virtual_rays() # A QQbasis for N_1 155 fan1_pivot_cones = [ fan1.embed(Cone([r])) for r in fan1_pivot_rays ] 118 156 119 # The fan2 cones as set(set( integers))157 # The fan2 cones as set(set(ray indices)) 120 158 fan2_cones = frozenset( 121 159 frozenset(cone.ambient_ray_indices()) 122 160 for cone in fan2.generating_cones() ) 123 161 124 162 # 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() 131 168 try: 132 m = matrix( fan1_basis).solve_right(matrix(fan2_basis))169 m = matrix(ZZ, fan1_basis).solve_right(matrix(ZZ, fan2_basis)) 133 170 m = m.change_ring(ZZ) 134 171 except (ValueError, TypeError): 135 172 continue # no solution 136 173 137 174 # 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) ] 139 176 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() ] 142 178 except ValueError: 143 179 continue 144 180 if graph_image_ray_indices != matrix_image_ray_indices: … … 150 186 for i in cone.ambient_ray_indices()) 151 187 for cone in fan1.generating_cones() ) 152 188 if image_cones == fan2_cones: 189 m.set_immutable() 153 190 yield m 154 191 155 192 … … 172 209 173 210 EXAMPLE:: 174 211 175 sage: rays = ((1, 1), (0, 1), (1, 1), ( 1, 0))212 sage: rays = ((1, 1), (0, 1), (1, 1), (3, 1)) 176 213 sage: cones = [(0,1), (1,2), (2,3), (3,0)] 177 214 sage: fan1 = Fan(cones, rays) 178 215 … … 193 230 Traceback (most recent call last): 194 231 ... 195 232 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 196 240 """ 197 241 generator = fan_isomorphism_generator(fan1, fan2) 198 242 try: