def g_quad(graph, node_list, gui=True): ''' Return quadratic form (numpy array) of networkx graph 'graph', ordered according to the node names in 'node_list'. Q(v,v) = weight(v) Q(v,w) = 1 if v, w are connected by an edge; 0 otherwise Thus Q is the adjacency matrix everywhere except the diagonal, and just the weights down the diagonal. ''' assert len(node_list) == len(graph.nodes(data=False)) assert is_forest(graph) num_bad = num_bad_vertices(graph, node_list) if num_bad > 2: if gui: tkMessageBox.showwarning('Bad vertices', 'More than two bad vertices. (There are %i.)'%num_bad) raise ValueError('More than two bad vertices. (There are %i.)'%num_bad) # create adjacency matrix, ordered according to node_list adj = nx.to_numpy_matrix(graph, nodelist=node_list, dtype=numpy.int) for index, node in enumerate(node_list): # change diagonal adj[index, index] = graph.node[node]['weight'] if not is_negative_definite(adj): if gui: tkMessageBox.showwarning('Quadratic form', 'Quadratic form is not negative definite') print adj raise ValueError('quadratric form is not negative definite') return adj
def s_quad_form(listdata, gui=True): ''' Returns the tuple (numpy.array quadratic_form, bool minus) of the weighted 'star-like' tree associated with the plumbed 3-manifold given by Seifert data 'listdata'. minus = True if orientation of the manifold described by listdata has been reversed, False otherwise Input: listdata [e, (p1, q1),...,(pr, qr)] Note: You should run correct_form on listdata; s_quad_form does not do this automatically The 'star-like' tree is formed as follows: Center node is a vertex with weight -e. There are r branches coming off of the center vertex. Each branch has the vertices [-a0, -a1, ... , -an], where a0,a1,...,an are the numbers in the continued fraction expansion of pi/qi, for each i. (Note: the continued fraction expansion has minus signs; see function 'cont_fraction'.) The quadratic form of the weighted graph is defined by Q(v, v) = m(v), where m is the weight of the vertex Q(v, w) = 1 if v, w are connected by an edge, 0 otherwise ''' new_data, minus = alter_data(listdata, gui) # make e > 0, -pi < qi < 0 tree = [new_data[0]] # list of weights in star tree [e, a0, a1,...] branch_lengths = [] # list of lengths of branches in star tree, not # including start node for pair in new_data[1:]: branch = cont_fraction(pair[0], -pair[1]) branch_lengths.append(len(branch)) tree.extend(branch) size = sum(branch_lengths) + 1 # add start node row = 0 column = 0 # make the quadratic form matrix quad = numpy.zeros(shape=(size, size), dtype=numpy.int) # fill in the diagonal for index in range(size): quad[index,index] = -tree[index] # fill in the others (upper right triangle) cur_position = 1 for length in branch_lengths: quad[0,cur_position] = 1 # star node for index in range(cur_position, cur_position+length-1): quad[index,index+1] = 1 # adjacent cur_position += length symmetric(quad) if not is_negative_definite(quad): if gui: tkMessageBox.showwarning('Quadratic form', 'Quadratic form is not negative definite') print quad raise ValueError('quadratric form is not negative definite') # check get the same thing from weighted_graph.py; also checks negative def. assert numpy.array_equal(quad, g_quad(make_graph(new_data), \ ['N%i' %num for num in range(size)])) return quad, minus