{ "cells": [ { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [], "source": [ "import numpy" ] }, { "cell_type": "code", "execution_count": 2, "metadata": {}, "outputs": [], "source": [ "# Author: Elisabetta Ghisu\n", "\n", "\"\"\"\n", "- Script containing functions for computing the shortest path kernel\n", "- The Floyd Warshall algorithm is first implemented\n", "- Then the SP is calculated\n", "\"\"\"\n", "\n", "\n", "#######################\n", "# - IMPORT PACKAGES - #\n", "#######################\n", "\n", "\n", "\n", "import numpy.matlib as matlib\n", "import numpy as np\n", "\n", "\"\"\"\n", "### FLOYD WARSHALL ALGORITHM\n", "Input:\n", "- Adjancency matrix A\n", "Output:\n", "- Shortest path matrix S\n", "\"\"\"\n", "\n", "def floyd_warshall(A):\n", "\n", "\t# nuber of nodes\n", "\tn = A.shape[0]\n", "\n", "\t# initialize shortes path matrix\n", "\tS = np.zeros(shape = (n,n))\n", "\n", "\tfor i in range(n):\n", "\t\tfor j in range(n):\n", "\t\t\tif A[i,j] == 0 and i!=j:\n", "\t\t\t\tS[i,j] = float(\"inf\")\n", "\t\t\telse:\n", "\t\t\t\tS[i,j] = A[i,j]\n", "\n", "\t# Compute the shortest path matrix\n", "\tfor k in range(n):\n", "\t\tfor i in range(n):\n", "\t\t\tfor j in range(n):\n", "\t\t\t\tif S[i,j] > S[i,k] + S[k,j]:\n", "\t\t\t\t\tS[i,j] = S[i,k] + S[k,j]\n", "\n", "\treturn S\t\t\t\t\t\t\t\t\n", "\n", "\n", "\n", "\"\"\"\n", "SHORTEST PATH KERNEL: This is a fast implementation of the shortest path\n", "kernel algorithm\n", "Inputs\n", "- Adjancency matrix\n", "- List of list of node labels for each graph\n", "- Total number of node labels \n", "Outputs\n", "- Kernel matrix\n", "- Feature matrix\n", "\"\"\"\n", "\n", "def sp_kernel_fast(adj_mat, labels, L):\n", "\n", "\t# Number of graphs\n", "\tn = len(adj_mat)\n", "\tL = int(L)\n", "\tS = []\n", "\n", "\t# shortest path matrices\n", "\tfor i in xrange(n):\n", "\t\tif i%1000 == 0 and i !=0:\n", " \t\t\tprint('haha') #( \"%d\" % i)\n", "\t\tS.append(floyd_warshall(adj_mat[i]))\n", "\t\n", "\t# maximum length of shortest paths in the dataset\n", "\tmax_path = 0\n", "\n", "\t# for each graph in dataset\n", "\tfor i in xrange(n):\n", "\n", "\t\tS_cur = np.copy(S[i])\n", "\t\tS_cur[S_cur == np.inf] = 0\n", "\t\tnew_max = np.max(S_cur)\n", "\t\t\n", "\t\tif new_max > max_path:\n", "\t\t\tmax_path = new_max # get max short path in all Ss\n", "\n", "\t# maximum length of shortest paths\n", "\tmax_path = int(max_path)\n", "\n", "\t# initialize feature matrix\n", "\tsp = np.zeros(((max_path + 1) * L * (L+1) /2,n))\n", "\n", "\t# compute feature map for shortest path\n", "\tfor i in xrange(n):\n", "\n", "\t\tif i % 1000 == 0:\n", "\t\t\tprint('haha') #\"Processed %d graphs\" %i\n", "\n", "\t\tS_graph = S[i]\n", "\t\tlabels_graph = np.asarray(labels[i].reshape((len(labels[i]),1)))\n", "\t\tlabels_graph = labels_graph + 1\n", "\t\t\n", "\t\tlabels_aux = matlib.repmat(labels_graph, 1, len(labels_graph))\n", "\t\t\n", "\t\tmin_lab = np.minimum(labels_aux, labels_aux.T)\n", "\t\t\n", "\t\tmax_lab = np.maximum(labels_aux, labels_aux.T)\n", "\t\tsub_path = np.triu(~(np.isinf(S_graph))).T\n", "\n", "\t\tmin_lab = min_lab[sub_path]\n", "\t\tmax_lab = max_lab[sub_path]\n", "\n", "\n", "\t\tind = S_graph[sub_path] * L * (L + 1) / 2 + (min_lab - 1) * (2*L + 2 - min_lab) / 2 + max_lab - min_lab\n", "\t\tind = ind.astype(int)\n", "\t\taccum = np.zeros((max_path + 1) * L * (L + 1) /2)\n", "\t\taccum[:ind.max() + 1] += np.bincount(ind.astype(int))\n", "\t\tsp[ind,i] = accum[ind]\n", "\t\n", "\tsum_cols = np.sum(sp, axis = 1)\n", "\tind_true = sum_cols != 0\n", "\tsp = sp[ind_true,:]\n", "\t\n", "\t# compute kernel matrix\n", "\tK = np.dot(sp.T,sp)\n", " \n", "\treturn K, sp" ] }, { "cell_type": "code", "execution_count": 3, "metadata": {}, "outputs": [ { "ename": "ModuleNotFoundError", "evalue": "No module named 'igraph'", "output_type": "error", "traceback": [ "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", "\u001b[0;31mModuleNotFoundError\u001b[0m Traceback (most recent call last)", "\u001b[0;32m\u001b[0m in \u001b[0;36m\u001b[0;34m\u001b[0m\n\u001b[1;32m 14\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 15\u001b[0m \u001b[0;31m# iGraph imports to handle graphs and for graph I/O\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m---> 16\u001b[0;31m \u001b[0;32mfrom\u001b[0m \u001b[0migraph\u001b[0m \u001b[0;32mimport\u001b[0m \u001b[0mGraph\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 17\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 18\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n", "\u001b[0;31mModuleNotFoundError\u001b[0m: No module named 'igraph'" ] } ], "source": [ "#Authors: Elisabetta Ghisu, Felipe Llinares Lopez\n", "\n", "\"\"\"\n", "- This script includes a list of functions for analyzing \n", "parsing and formatting graphs\n", "- The graphs are given in graphml format\n", "- It also contains functions for loading, processing the graphs\n", "and extract graph statistics\n", "\"\"\"\n", "\n", "\n", "import numpy as np\n", "from numpy import genfromtxt\n", "\n", "# iGraph imports to handle graphs and for graph I/O\n", "from igraph import Graph\n", "\n", "\n", "# ---------------------------------GRAPHML I/O FUNCTIONS------------------------------------ #\n", "\n", "# INPUT:\n", "# filenames_graphs: list of GraphML files, where each file contains one graph in the dataset\n", "# filename_labels: text file with labels corresponding to each graph in the dataset, in the same order as they are in\n", "# filename_graphs\n", "# OUTPUT:\n", "# G: A list containing one iGraph object for each graph in the dataset\n", "# Y: A Numpy array containing the labels corresponding to each graph, in the same order as G\n", "def load_graphml(filenames_graphs, filename_labels):\n", " G = []\n", " for fname in filenames_graphs:\n", " G.append(Graph.Read_GraphML(fname))\n", " Y = genfromtxt(filename_labels)\n", " return (G, Y)\n", "\n", "\n", "# Loads a list of paths to GraphML files from filename_list\n", "def load_file_list(filename_flist):\n", " f = open(filename_flist, 'r')\n", " f_graphs = []\n", " for line in f:\n", " f_graphs.append(line.strip())\n", " f.close()\n", " return f_graphs\n", "\n", "\n", "# --------------------------------COMPUTE STATISTICS---------------------------------------- #\n", "\n", "\n", "# Retrieve labels of all vertices belonging to any graph in the list of iGraph objects G and\n", "# returns the entire list, and a list with the alphabet of the vertex labels\n", "def get_all_vertex_labels(G, att_name='label'):\n", " v_l = []\n", " for g in G:\n", " v_l += g.vs[att_name]\n", " return (v_l, np.unique(v_l))\n", "\n", "\n", "# Retrieve labels of all edges belonging to any graph in the list of iGraph objects G and\n", "# returns the entire list, and a list with the alphabet of the edge labels\n", "def get_all_edge_labels(G, att_name='label'):\n", " e_l = []\n", " for g in G:\n", " e_l += g.es[att_name]\n", " return (e_l, np.unique(e_l))\n", "\n", "\n", "# Returns a list where each element is itself the adjacency list of the corresponding graph\n", "# The adjacency lit of a graph has the following format:\n", "# it is a list where each element is a list containing the id of adjacent nodes\n", "def get_adj_list(G):\n", " ad_l = []\n", " for g in G:\n", " ad_l.append(g.get_adjlist())\n", " return ad_l\n", "\n", "# Returns a list where each element is the adjacency matrix of the graph \n", "# The adjancency matrix is in iGraph format\n", "def get_adj_mat(G):\n", " ad_m = []\n", " for g in G:\n", " ad_m.append(g.get_adjacency())\n", " return ad_m\n", "\n", "# Returns a list where each element contains the nodes label for a graph\n", "def get_node_labels(G, att_name = 'label'):\n", " node_l = []\n", " for g in G:\n", " node_l.append(g.vs[att_name])\n", " return node_l\n", "\n", "\n", "\n", "# ----------------- LOAD AND PROCESS THE GRAPHS --------------- #\n", "\n", "\n", "\"\"\"\n", "Inputs:\n", "- list of graphs file\n", "- labels file\n", "- path to the data folder\n", "Outputs:\n", "- List of node labels\n", "- List of adjancency lists\n", "- List of graphs in graphml format\n", "- Targets\n", "- number of classes\n", "- sample size\n", "\"\"\"\n", "\n", "\n", "def load_and_process(filenames_graphs, filename_labels, path_to_dataset):\n", "\n", " # load a list of names to graphml files\n", " f_graphs = load_file_list(filenames_graphs)\n", " # sample size\n", " n = len(f_graphs)\n", "\n", " # create a list of paths to the files\n", " f_graphs_path =[]\n", "\n", " # for each graph in dataset\n", " for i in range(n):\n", "\n", " # index the graph\n", " graph_name = f_graphs[i]\n", "\n", " # path to the data folder\n", " path = \"%s/%s\" % (path_to_dataset, graph_name)\n", " f_graphs_path.append(path)\n", "\n", " # If the data is DD have to delete an element (corrupted file)\n", " if graph_name == \"DD\":\n", " del f_graphs_path[148]\n", " n = n-1\n", "\n", " # Load the graphs in graphml format\n", " # G is a llist of graphml graph\n", " # Y is an array of targets\n", " G,Y = load_graphml(f_graphs_path, filename_labels)\n", "\n", " # Delete corrupted file in DD\n", " if graph_name == \"DD\": \n", " Y = np.delete(Y, 148)\n", "\n", " # get adjacency list and matrix for all the graphs in G\n", " ad_list = get_adj_list(G)\n", " ad_mat = get_adj_mat(G)\n", "\n", " # get a list containing lists of node labels\n", " node_label = get_node_labels(G)\n", "\n", " return node_label, ad_list, G, Y\n", "\n", "\n", "\n", "\"\"\"\n", "RENAME NODES: function to rename nodes from 0,...,num_nodes\n", "Input\n", "- list of list of node labels in each graph\n", "Output\n", "- L: total number of different labels in the dataset\n", "- node_label: new renamed labels\n", "\"\"\"\n", "\n", "def rename_nodes(node_label): \n", " \n", " # number of graphs in the dataset\n", " n = len(node_label)\n", "\n", " # labels will store the new labels\n", " labels = [0] * n\n", "\n", " # disctionary containing the map from the old to the new labels\n", " label_lookup = {}\n", "\n", " # counter of unique labels\n", " label_counter = 0\n", "\n", " # for each graph in dataset\n", " for i in range(n):\n", "\n", "\n", " # number of nodes in graph[i]\n", " num_nodes = len(node_label[i]) \n", "\n", " # will be used to store the new labels\n", " labels[i] = np.zeros(num_nodes, dtype = np.uint64) # positive integers\n", "\n", " # for each node in the graph\n", " for j in range(num_nodes):\n", "\n", " # the node label to a string\n", " l_node_str = str(np.copy(node_label[i][j]))\n", " \n", " # if the string has not been observed yet\n", " # the corresponding node is assigned a new label\n", " # otherwise it will be named with the same label\n", " # already assigned to an identical string\n", "\n", " if not label_lookup.has_key(l_node_str):\n", " label_lookup[l_node_str] = label_counter\n", " labels[i][j] = label_counter \n", " label_counter += 1\n", " else:\n", " labels[i][j] = label_lookup[l_node_str]\n", "\n", " # total number of labels in the dataset\n", " L = label_counter\n", " print('haha') #'Number of original labels %d' % L \n", "\n", " return L, labels" ] }, { "cell_type": "code", "execution_count": 4, "metadata": {}, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ "usage: ipykernel_launcher.py [-h] --dataset DATASET\n", "ipykernel_launcher.py: error: the following arguments are required: --dataset\n" ] }, { "ename": "SystemExit", "evalue": "2", "output_type": "error", "traceback": [ "An exception has occurred, use %tb to see the full traceback.\n", "\u001b[0;31mSystemExit\u001b[0m\u001b[0;31m:\u001b[0m 2\n" ] }, { "name": "stderr", "output_type": "stream", "text": [ "/usr/local/lib/python3.6/dist-packages/IPython/core/interactiveshell.py:3273: UserWarning: To exit: use 'exit', 'quit', or Ctrl-D.\n", " warn(\"To exit: use 'exit', 'quit', or Ctrl-D.\", stacklevel=1)\n" ] } ], "source": [ "# Author: Elisabetta Ghisu\n", "\n", "\"\"\"\n", "- Script for computing the kernel matrix and features map \n", "using shortest path kernel\n", "\"\"\"\n", "\n", "###########################\n", "# --- IMPORT PACKAGES --- #\n", "###########################\n", "\n", "import numpy as np\n", "import argparse\n", "import os\n", "import pickle\n", "\n", "from numpy import genfromtxt\n", "\n", "# from sp_functions import *\n", "# from parse_graphs import *\n", "\n", "\n", "\n", "##############################\n", "### Command Line Arguments ###\n", "##############################\n", "\n", "parser = argparse.ArgumentParser(description = \"Compute kernel and features matrices via shortest path kernel\")\n", "parser.add_argument(\"--dataset\", required = True, help = \"Name of the dataset\")\n", "args = parser.parse_args()\n", "\n", "\n", "#####################\n", "### LOAD THE DATA ###\n", "#####################\n", "\n", "\"\"\"\n", "- Here we load the data input and targets\n", "- The data are assumed to be in graph formats\n", "- They should be in graphml format \n", "\"\"\"\n", "\n", "# path to the list of graphs and dataset\n", "filenames_graphs = \"data/%s.list\" % (args.dataset)\n", "path_to_dataset = \"data/%s\" % (args.dataset) \n", "\n", "# Load the targets\n", "filename_labels = \"data/%s_label.txt\" % (args.dataset)\n", "\n", "# load and process graphs\n", "node_label, ad_list, G, Y = load_and_process(filenames_graphs, filename_labels, path_to_dataset)\n", "\n", "# output directory\n", "out_path = \"kernel_matrices/%s/sp\" % args.dataset\n", "\n", "# If the output directory does not exist, then create it\n", "if not os.path.exists(out_path):\n", " os.makedirs(out_path)\n", "\n", "\n", "#########################\n", "# --- SHORTEST PATH --- #\n", "#########################\n", "\n", "\n", "# assign labels starting from zero to the nodes\n", "L, labels = rename_nodes(node_label)\n", "\n", "\n", "# Compute adjancency matrix \n", "adj_mat = get_adj_mat(G)\n", "\n", "# Compute kernel and feature maps using shortest path\n", "K, phi = sp_kernel_fast(adj_mat, labels, L)\n", "\n", "# save kernel matrix\n", "file_name = \"%s/%s_ker_mat\" % (out_path, args.dataset)\n", "np.save(file_name, K)\n", "\n", "# save feature map\n", "file_name = \"%s/%s_phi_map\" % (out_path, args.dataset)\n", "np.save(file_name, phi)" ] }, { "cell_type": "code", "execution_count": 5, "metadata": {}, "outputs": [], "source": [ "import networkx as nx\n", " \n", "def loadCT(filename):\n", " \"\"\"load data from .ct file.\n", " \n", " Notes\n", " ------ \n", " a typical example of data in .ct is like this:\n", " \n", " 3 2 <- number of nodes and edges\n", " 0.0000 0.0000 0.0000 C <- each line describes a node, the last parameter in which is the label of the node, representing a chemical element @Q what are the first 3 numbers?\n", " 0.0000 0.0000 0.0000 C\n", " 0.0000 0.0000 0.0000 O\n", " 1 3 1 1 <- each line describes an edge, the first two numbers represent two nodes of the edge, the last number represents the label. @Q what are the 3th numbers?\n", " 2 3 1 1\n", " \"\"\"\n", " content = open(filename).read().splitlines()\n", " G = nx.Graph(name=str(content[0])) # set name of the graph\n", " tmp = content[1].split(\" \")\n", " if tmp[0] == '':\n", " nb_nodes = int(tmp[1]) # number of the nodes\n", " nb_edges = int(tmp[2]) # number of the edges\n", " else:\n", " nb_nodes = int(tmp[0])\n", " nb_edges = int(tmp[1])\n", "\n", " for i in range(0, nb_nodes):\n", " tmp = content[i + 2].split(\" \")\n", " tmp = [x for x in tmp if x != '']\n", " G.add_node(i, label=tmp[3])\n", "\n", " for i in range(0, nb_edges):\n", " tmp = content[i + G.number_of_nodes() + 2].split(\" \")\n", " tmp = [x for x in tmp if x != '']\n", " G.add_edge(int(tmp[0]) - 1, int(tmp[1]) - 1, label=int(tmp[3]))\n", " return G\n", "\n", "\n", "def loadGXL(filename):\n", " import networkx as nx\n", " import xml.etree.ElementTree as ET\n", "\n", " tree = ET.parse(filename)\n", " root = tree.getroot()\n", " index = 0\n", " G = nx.Graph()\n", " dic={}\n", " for node in root.iter('node'):\n", " label = node.find('attr')[0].text\n", " dic[node.attrib['id']] = index\n", " G.add_node(index, id=node.attrib['id'], label=label)\n", " index += 1\n", " \n", " for edge in root.iter('edge'):\n", " label = edge.find('attr')[0].text\n", " G.add_edge(dic[edge.attrib['from']], dic[edge.attrib['to']], label=label)\n", " return G\n", " \n", "def loadDataset(filename):\n", " \"\"\"load file list of the dataset.\n", " \"\"\"\n", " from os.path import dirname, splitext\n", "\n", " dirname_dataset = dirname(filename)\n", " extension = splitext(filename)[1][1:]\n", " data = []\n", " y = []\n", " if(extension == \"ds\"):\n", " content = open(filename).read().splitlines()\n", " for i in range(0, len(content)):\n", " tmp = content[i].split(' ')\n", " data.append(loadCT(dirname_dataset + '/' + tmp[0].replace('#', '', 1))) # remove the '#'s in file names\n", " y.append(float(tmp[1]))\n", " elif(extension == \"cxl\"):\n", " import xml.etree.ElementTree as ET\n", "\n", " tree = ET.parse(filename)\n", " root = tree.getroot()\n", " data = []\n", " y = []\n", " for graph in root.iter('print'):\n", " mol_filename = graph.attrib['file']\n", " mol_class = graph.attrib['class']\n", " data.append(loadGXL(dirname_dataset + '/' + mol_filename))\n", " y.append(mol_class)\n", "\n", " return data, y" ] }, { "cell_type": "code", "execution_count": 6, "metadata": {}, "outputs": [], "source": [ "import sys\n", "import pathlib\n", "sys.path.insert(0, \"../../\")\n", "\n", "\n", "import networkx as nx\n", "import numpy as np\n", "import time\n", "\n", "from gklearn.utils.utils import getSPGraph\n", "\n", "\n", "def spkernel(Gn):\n", " \"\"\"Transform graph G to its corresponding shortest-paths graph using Floyd-transformation.\n", " \n", " Parameters\n", " ----------\n", " G : NetworkX graph\n", " The graph to be tramsformed.\n", " \n", " Return\n", " ------\n", " S : NetworkX graph\n", " The shortest-paths graph corresponding to G.\n", " \n", " References\n", " ----------\n", " [1] Borgwardt KM, Kriegel HP. Shortest-path kernels on graphs. InData Mining, Fifth IEEE International Conference on 2005 Nov 27 (pp. 8-pp). IEEE.\n", " \"\"\"\n", " Kmatrix = np.zeros((len(Gn), len(Gn)))\n", " \n", " Sn = [] # get shortest path graphs of Gn\n", " for i in range(0, len(Gn)):\n", " Sn.append(getSPGraph(Gn[i]))\n", " \n", "# print(S1.nodes(data = True))\n", "# print(S2.nodes(data = True))\n", "# print(S1.edges(data = True))\n", "# print(S2.edges(data = True))\n", " \n", " start_time = time.time()\n", " for i in range(0, len(Gn)):\n", " for j in range(i, len(Gn)):\n", " for e1 in Sn[i].edges(data = True):\n", " for e2 in Sn[j].edges(data = True): \n", " if e1[2]['cost'] != 0 and e1[2]['cost'] == e2[2]['cost'] and ((e1[0] == e2[0] and e1[1] == e2[1]) or (e1[0] == e2[1] and e1[1] == e2[0])):\n", " Kmatrix[i][j] += 1\n", " Kmatrix[j][i] += (0 if i == j else 1)\n", " \n", " print(\"--- %s seconds ---\" % (time.time() - start_time))\n", " \n", " return Kmatrix" ] }, { "cell_type": "code", "execution_count": 8, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[[0. 2. 3. 1. 2.]]\n", "{0: {0: [0], 3: [0, 3], 1: [0, 3, 1], 4: [0, 3, 4], 2: [0, 3, 4, 2]}, 1: {1: [1], 3: [1, 3], 0: [1, 3, 0], 4: [1, 3, 4], 2: [1, 3, 4, 2]}, 2: {2: [2], 4: [2, 4], 3: [2, 4, 3], 0: [2, 4, 3, 0], 1: [2, 4, 3, 1]}, 3: {3: [3], 0: [3, 0], 1: [3, 1], 4: [3, 4], 2: [3, 4, 2]}, 4: {4: [4], 2: [4, 2], 3: [4, 3], 0: [4, 3, 0], 1: [4, 3, 1]}}\n", "[[0. 2. 3. 1. 2.]\n", " [2. 0. 3. 1. 2.]\n", " [3. 3. 0. 2. 1.]\n", " [1. 1. 2. 0. 1.]\n", " [2. 2. 1. 1. 0.]]\n" ] }, { "data": { "image/png": "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\n", "text/plain": [ "
" ] }, "metadata": { "needs_background": "light" }, "output_type": "display_data" }, { "name": "stdout", "output_type": "stream", "text": [ "{(0, 1): 2.0, (0, 2): 3.0, (0, 3): 1.0, (0, 4): 2.0, (1, 2): 3.0, (1, 3): 1.0, (1, 4): 2.0, (2, 3): 2.0, (2, 4): 1.0, (3, 4): 1.0}\n" ] }, { "data": { "image/png": "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\n", "text/plain": [ "
" ] }, "metadata": { "needs_background": "light" }, "output_type": "display_data" } ], "source": [ "dataset, y = loadDataset(\"../../datasets/acyclic/dataset_bps.ds\")\n", "G1 = dataset[12]\n", "\n", "nx.draw_networkx(G1)\n", "# print(list(dataset[12][4]))\n", "\n", "l = nx.shortest_path(G1)\n", "\n", "l2 = nx.floyd_warshall_numpy(G1)\n", "print(np.array(l2[0]))\n", "print(l)\n", "print(l2)\n", "from matplotlib import pyplot as plt\n", "plt.show()\n", "\n", "S = getSPGraph(G1)\n", "nx.draw_networkx(S)\n", "pos = nx.spring_layout(S)\n", "edge_labels = nx.get_edge_attributes(S,'cost')\n", "print(edge_labels)\n", "nx.draw_networkx_edge_labels(S, pos, edge_labels = edge_labels)\n", "plt.show()" ] }, { "cell_type": "code", "execution_count": 16, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "--- 8.196406841278076 seconds ---\n", "[[ 3. 1. 3. ... 1. 1. 1.]\n", " [ 1. 6. 1. ... 0. 0. 3.]\n", " [ 3. 1. 3. ... 1. 1. 1.]\n", " ...\n", " [ 1. 0. 1. ... 55. 21. 7.]\n", " [ 1. 0. 1. ... 21. 55. 7.]\n", " [ 1. 3. 1. ... 7. 7. 55.]]\n" ] } ], "source": [ "dataset, y = loadDataset(\"../../datasets/acyclic/dataset_bps.ds\")\n", "G1 = dataset[12]\n", "G2 = dataset[20]\n", "Kmatrix = spkernel(dataset)\n", "\n", "print(Kmatrix)" ] } ], "metadata": { "kernelspec": { "display_name": "Python 3", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.6.7" } }, "nbformat": 4, "nbformat_minor": 2 }