def testBFS(): g = graph.Graph() nodes = g.add_tree((1, (2, 3), (2, 3))) data = map(lambda x: x.data, g.bfs(nodes[0])) assert data == [1, 2, 2, 3, 3] # test undirected version data = map(lambda x: x.data, g.undirected_bfs(nodes[2][1])) assert data == [3, 2, 1, 2, 3] # test node with two ingoing edges g = graph.Graph() nodes = g.add_tree((1, 2, (2, 3))) g.add_edge(nodes[1], nodes[2][1]) data = map(lambda x: x.data, g.bfs(nodes[0])) assert data == [1, 2, 2, 3]
def testDFS(): g = graph.Graph() nodes = g.add_tree((1, (2, 3), (2, 3))) data = [x.data for x in g.dfs(nodes[0])] assert data == [1, 2, 3, 2, 3] # test undirected version data = [x.data for x in g.undirected_dfs(nodes[2][1])] assert data == [3, 2, 1, 2, 3] # test node with two ingoing edges g = graph.Graph() nodes = g.add_tree((1, 2, (2, 3))) g.add_edge(nodes[1], nodes[2][1]) data = [x.data for x in g.dfs(nodes[0])] assert data == [1, 2, 3, 2]
def testAddFullConnectivity(): g = graph.Graph() layer0 = g.add_nodes(10) layer1 = g.add_nodes(5) g.add_full_connectivity(layer0, layer1) assert len(g.edges) == 5 * 10 assert map(lambda x: x.out_degree(), layer0) == [5] * 10 assert map(lambda x: x.in_degree(), layer1) == [10] * 5
def testAddFullConnectivity(): g = graph.Graph() layer0 = g.add_nodes(10) layer1 = g.add_nodes(5) g.add_full_connectivity(layer0, layer1) assert len(g.edges) == 5 * 10 assert [x.out_degree() for x in layer0] == [5] * 10 assert [x.in_degree() for x in layer1] == [10] * 5
def testAddTree(): g = graph.Graph() a = None nodes = g.add_tree((a, a, (a, a, a))) assert len(g.nodes) == 5 assert len(g.edges) == 4 out_deg = graph.recursive_map(lambda x: x.out_degree(), nodes) assert out_deg == [2, 0, [2, 0, 0]] in_deg = graph.recursive_map(lambda x: x.in_degree(), nodes) assert in_deg == [0, 1, [1, 1, 1]]
def testGetNeighbors(): g = graph.Graph() nodes = g.add_tree((1, 2, (2, 3))) g.add_edge(nodes[1], nodes[2][1]) outnodes = nodes[0].out_neighbors() assert nodes[1] in outnodes and nodes[2][0] in outnodes innodes = nodes[2][1].in_neighbors() assert nodes[2][0] in innodes and nodes[2][0] in innodes inoutnodes = nodes[1].neighbors() assert nodes[0] in inoutnodes and nodes[2][1] in inoutnodes
def testAddNode(): # add_node g = graph.Graph() nnodes = 5 for i in xrange(nnodes): g.add_node() assert len( g.nodes) == nnodes, "Wrong number of nodes, expected: %d, got :%d" % ( nnodes, len(g.nodes)) # add nodes g = graph.Graph() g.add_nodes(5) assert len( g.nodes) == nnodes, "Wrong number of nodes, expected: %d, got :%d" % ( nnodes, len(g.nodes)) g = graph.Graph() g.add_nodes([None] * nnodes) assert len( g.nodes) == nnodes, "Wrong number of nodes, expected: %d, got :%d" % ( nnodes, len(g.nodes))
def testRemoveEdge(): g = graph.Graph() n0 = g.add_node() n1 = g.add_node() ed = g.add_edge(n0, n1) g.remove_edge(ed) assert len( g.edges) == 0, "Wrong number of edges, expected: 0, got :%d" % len( g.edges) assert n0.out_degree( ) == 0, "Wrong out_degree, expected: 0, got: %d." % n0.out_degree() assert n1.in_degree( ) == 0, "Wrong in_degree, expected: 0, got: %d." % n1.in_degree()
def testGetEdge(): g = graph.Graph() nds = g.add_nodes(4) ed1 = g.add_edge(nds[0], nds[2]) ed2 = g.add_edge(nds[1], nds[2]) ed3 = g.add_edge(nds[2], nds[3]) assert set(nds[2].get_edges_in()) == set([ed1, ed2]) assert set(nds[2].get_edges_out()) == set([ed3]) assert set(nds[2].get_edges()) == set([ed1, ed2, ed3]) assert set(nds[2].get_edges_in(from_=nds[1])) == set([ed2]) assert set(nds[2].get_edges_out(to_=nds[3])) == set([ed3]) ed4 = g.add_edge(nds[3], nds[2]) assert set(nds[2].get_edges(neighbor=nds[3])) == set([ed3, ed4])
def testConnectedComponents(): g = graph.Graph() nds0 = g.add_tree((1, 1, 1)) nds1 = g.add_tree((2, 2, 2)) comps = g.connected_components() comps = graph.recursive_map(lambda x: x.data, comps) assert len(comps) == 2 assert comps[0] == [1, 1, 1] assert comps[1] == [2, 2, 2] assert not g.is_weakly_connected() # connect graph g.add_edge(nds0[0], nds1[0]) assert g.is_weakly_connected()
def testTopologicalSort(): g = graph.Graph() # the values correspond to the number of in-edges nds = g.add_tree((0, 3, 1, 2)) g.add_edge(nds[2], nds[1]) g.add_edge(nds[2], nds[3]) g.add_edge(nds[3], nds[1]) data = map(lambda x: x.data, g.topological_sort()) assert data == [0, 1, 2, 3] # make graph cyclic g.add_edge(nds[1], nds[0]) try: g.topological_sort() raise Exception('Expected graph.GraphTopologicalException.') except graph.GraphTopologicalException: pass
def testAddEdge(): g = graph.Graph() nnodes = 5 nds = [g.add_node() for i in xrange(nnodes)] eds = [g.add_edge(nds[i], nds[i + 1]) for i in xrange(nnodes - 1)] assert len( g.edges ) == nnodes - 1, "Wrong number of edges, expected: %d, got :%d" % ( nnodes - 1, len(g.edges)) # the last nnodes-1 nodes should have in_degree==1, # and the first nnodes-1 out_degree==1 for i in xrange(nnodes): if i > 0: assert nds[i].in_degree( ) == 1, "Wrong in_degree, expected: 1, got: %d." % nds[ i].in_degree() if i < nnodes - 1: assert nds[i].out_degree( ) == 1, "Wrong out_degree, expected: 1, got: %d." % nds[ i].out_degree()
def __init__(self, start_poss=None, eps_b=0.2, eps_n=0.006, max_age=50, lambda_=100, alpha=0.5, d=0.995, max_nodes=2147483647, input_dim=None, dtype=None): """Initializes an object of type 'GrowingNeuralGasNode'. :param start_poss: Sequence of two arrays containing the position of the first two nodes in the GNG graph. If unspecified, the initial nodes are chosen with a random position generated from a gaussian distribution with zero mean and unit variance. :type start_poss: list, tuple, numpy.ndarray :param eps_b: Coefficient of movement of the nearest node to a new data point. Typical values are 0 < eps_b << 1 . Default: 0.2 :type eps_b: float :param eps_n: Coefficient of movement of the neighbours of the nearest node to a new data point. Typical values are 0 < eps_n << eps_b . Default: 0.006 :type eps_n: float :param max_age: Remove an edge after `max_age` updates. Typical values are 10 < max_age < lambda. Default: 50 :type max_age: int :param lambda_: Insert a new node after `lambda_` steps. Typical values are O(100). Default: 100 :type lambda_: int :param alpha: When a new node is inserted, multiply the error of the nodes from which it generated by 0<alpha<1. A typical value is 0.5. Default: 0.5 :type alpha: float :param d: Each step the error of the nodes are multiplied by 0<d<1. Typical values are close to 1. Default: 0.995 :type d: float :param max_nodes: Maximal number of nodes in the graph. :type max_nodes: int :param input_dim: The input dimensionality. :type input_dim: int :param dtype: The datatype. :type dtype: numpy.dtype or str """ self.graph = graph.Graph() self.tlen = 0 #copy parameters (self.eps_b, self.eps_n, self.max_age, self.lambda_, self.alpha, self.d, self.max_nodes) = (eps_b, eps_n, max_age, lambda_, alpha, d, max_nodes) super(GrowingNeuralGasNode, self).__init__(input_dim, None, dtype) if start_poss is not None: if self.dtype is None: self.dtype = start_poss[0].dtype node1 = self._add_node(self._refcast(start_poss[0])) node2 = self._add_node(self._refcast(start_poss[1])) self._add_edge(node1, node2)
def __init__( self, num_nodes=10, start_poss=None, epsilon_i=0.3, # initial epsilon epsilon_f=0.05, # final epsilon lambda_i=30., # initial lambda lambda_f=0.01, # final lambda max_age_i=20, # initial edge lifetime max_age_f=200, # final edge lifetime max_epochs=100, n_epochs_to_train=None, input_dim=None, dtype=None): """Initializes an object of type 'NeuralGasNode'. Default parameters taken from the original publication. :param num_nodes: Number of nodes to use. Ignored if start_poss is given. Default is 10. :type num_nodes: int :param start_poss: Sequence of two arrays containing the position of the first two nodes in the GNG graph. In unspecified, the initial nodes are chosen with a random position generated from a gaussian distribution with zero mean and unit variance. Default is None. :type start_poss: list, tuple or numpy.ndarray :param epsilon_i: Initial value of epsilon. Fraction of the distance between the closest node and the presented data point by which the node moves towards the data point in an adaptation step. Epsilon decays during training by e(t) = e_i(e_f/e_i)^(t/t_max) with t being the epoch. Default is 0.3. :type epsilon_i: float :param epsilon_f: Final value of epsilon. Fraction of the distance between the closest node and the presented data point by which the node moves towards the data point in an adaptation step. Epsilon decays during training by e(t) = e_i(e_f/e_i)^(t/t_max) with t being the epoch. Default is 0.05. :type epsilon_f: float :param lambda_i: Initial value of lambda. Lambda influences how the weight change of nodes in the ranking decreases with lower rank. It is sometimes called the "neighborhood factor". Lambda decays during training in the same manner as epsilon does. Default is 30. . :type lambda_i: float :param lambda_f: Final value of lambda. Lambda influences how the weight change of nodes in the ranking decreases with lower rank. It is sometimes called the "neighborhood factor". Lambda decays during training in the same manner as epsilon does. Default is 0.01. :type lambda_f: float :param max_age_i: Initial lifetime, after which an edge will be removed. Lifetime is measured in terms of adaptation steps, i.e., presentations of data points. It decays during training like epsilon does. Default is 20. :type max_age_i: int :param max_age_f: Final lifetime, after which an edge will be removed. Lifetime is measured in terms of adaptation steps, i.e., presentations of data points. It decays during training like epsilon does. Default is 200. :type max_age_f: int :param max_epochs: Number of epochs to train. One epoch has passed when all data points from the input have been presented once. The default in the original publication was 40000, but since this has proven to be impractically high too high for many real-world data sets, we adopted a default value of 100. :type max_epochs: int :param n_epochs_to_train: Number of epochs to train on each call. Useful for batch learning and for visualization of the training process. Default is to train once until max_epochs is reached. :type n_epochs_to_train: int :param input_dim: The input dimensionality. :type input_dim: int :param dtype: The datatype. :type dtype: numpy.dtype or str """ self.graph = graph.Graph() if n_epochs_to_train is None: n_epochs_to_train = max_epochs #copy parameters self.num_nodes = num_nodes self.start_poss = start_poss self.epsilon_i = epsilon_i self.epsilon_f = epsilon_f self.lambda_i = lambda_i self.lambda_f = lambda_f self.max_age_i = max_age_i self.max_age_f = max_age_f self.max_epochs = max_epochs self.n_epochs_to_train = n_epochs_to_train super(GrowingNeuralGasNode, self).__init__(input_dim, None, dtype) if start_poss is not None: if self.num_nodes != len(start_poss): self.num_nodes = len(start_poss) if self.dtype is None: self.dtype = start_poss[0].dtype for node_ind in range(self.num_nodes): self._add_node(self._refcast(start_poss[node_ind])) self.epoch = 0
def __init__(self, start_poss=None, eps_b=0.2, eps_n=0.006, max_age=50, lambda_=100, alpha=0.5, d=0.995, max_nodes=2147483647, input_dim=None, dtype=None): """Growing Neural Gas algorithm. :Parameters: start_poss sequence of two arrays containing the position of the first two nodes in the GNG graph. If unspecified, the initial nodes are chosen with a random position generated from a gaussian distribution with zero mean and unit variance. eps_b coefficient of movement of the nearest node to a new data point. Typical values are 0 < eps_b << 1 . Default: 0.2 eps_n coefficient of movement of the neighbours of the nearest node to a new data point. Typical values are 0 < eps_n << eps_b . Default: 0.006 max_age remove an edge after `max_age` updates. Typical values are 10 < max_age < lambda. Default: 50 `lambda_` insert a new node after `lambda_` steps. Typical values are O(100). Default: 100 alpha when a new node is inserted, multiply the error of the nodes from which it generated by 0<alpha<1. A typical value is 0.5. Default: 0.5 d each step the error of the nodes are multiplied by 0<d<1. Typical values are close to 1. Default: 0.995 max_nodes maximal number of nodes in the graph. Default: 2^31 - 1 """ self.graph = graph.Graph() self.tlen = 0 #copy parameters (self.eps_b, self.eps_n, self.max_age, self.lambda_, self.alpha, self.d, self.max_nodes) = (eps_b, eps_n, max_age, lambda_, alpha, d, max_nodes) super(GrowingNeuralGasNode, self).__init__(input_dim, None, dtype) if start_poss is not None: if self.dtype is None: self.dtype = start_poss[0].dtype node1 = self._add_node(self._refcast(start_poss[0])) node2 = self._add_node(self._refcast(start_poss[1])) self._add_edge(node1, node2)