API

Introduction

This part of the documentation covers the the interface for creating an searching graphs using the fornax package. For the full documentation of the module api see fornax.api module.

All of the functionality in fornax can be accessed via the follwoing three classes.

Connection is used to manage a connection to a SQL database. GraphHandle and QueryHandle are used to create, insert update and delete graphs and queries.

Connection API

Fornax stores and queries graphs using a database via a database connection. Connection manages the lifecycle of this database connection, the creation of database schema (if required) and any cleanup once the connection is closed.

class fornax.api.Connection(url, **kwargs)[source]

Create a new database connection. If the database is empty Connection will create any missing schema.

Currrently sqlite and postgresql are activly supported as backend databases.

In addition to the open/close syntax, Connection supports the context manager syntax where the context is treaded as a transaction. Any changes will be automatically rolled back in the event of an exception:

with Connection("postgres:://user/0.0.0.0./mydb") as conn:
    graph = fornax.GraphHandle.create(conn)
Parameters:url (str) – dialect[+driver]://user:password@host/dbname[?key=value..]
close()[source]

Close the fornax database connection and free any connections in the connection pool

open()[source]

Open the fornax database connection and create any absent tables and indicies

Graph API

Since Graphs are persisted in a database they are not represented directly by any object. Rather, graphs are accessed via a graph handle which permits the user to manipulate graphs via a Connection instance.

class fornax.api.GraphHandle(connection: fornax.api.Connection, graph_id: int)[source]

Create a handle to an existing graph with id graph_id accessed via connection.

Parameters:
  • connection (Connection) – fornax database connection
  • graph_id (int) – unique id for an existing graph
add_edges(sources: Iterable, targets: Iterable, **kwargs)[source]

Append edges to a graph representing relationships between nodes

Parameters:
  • sources (typing.Iterable) – node id_src
  • targets (typing.Iterable) – node id_src

Keyword arguments can be used to attach metadata to the edges. For example to add three edges with a relationship attribute friend or foe:

graph_handle.add_edges(
    sources=[0, 1, 2],
    targets=[1, 2, 0],
    relationship=['friend', 'friend', 'foe']
)

Keyword arguments can be used to attach any arbitrary JSON serialisable data to edges.

Note

The following reserved keywords are not reserved and will raise an exception

  • start
  • end
  • type
  • weight
add_nodes(**kwargs)[source]

Append nodes to a graph

Parameters:id_src (Iterable) – An iterable of unique hashable identifiers, default None

Keyword arguments can be used to attached arbitrary JSON serialised metadata to each node:

#  create 3 nodes with ids: 0, 1, 2
#  and names 'Anne', 'Ben', 'Charles'
graph_handle.add_nodes(names=['Anne', 'Ben', 'Charles'])

By default, each node will be assigned a sequential integer id starting from 0. A custom id can be assigned using the id_src keyword provided that all of the ids are hashable:

#  create 3 nodes with ids: 'Anne', 'Ben', 'Charles'
#  and no explicit name field
graph_handle.add_nodes(id_src=['Anne', 'Ben', 'Charles'])

Note

id is a reserved keyword argument which will raise an exception

classmethod create(connection: fornax.api.Connection)[source]

Create a new empty graph via connection and return a GraphHandle to it

Parameters:connection (Connection) – a fornax database connection
Returns:GraphHandle to a new graph
Return type:GraphHandle
delete()[source]

Delete this graph.

Delete the graph accessed through graph handle and all of the associated nodes and edges.

graph_id

Get the unique id for this graph

Graph id’s are automaticly assigned at creation time.

classmethod read(connection: fornax.api.Connection, graph_id: int)[source]

Create a new GraphHandle to an existing graph with unique identifier graph_id

Parameters:
  • connection (Connection) – a fornax database connection
  • graph_id (int) – unique identifier for an existing graph
Returns:

A new graph handle to an existing graph

Return type:

GraphHandle

Query API

Like Graphs, queries exist in a database and a accessed via a handle. Queries are executed using the QueryHandle.execute() method.

A query brings together three important concenpts.

A target graph is the graph which is going to be searched.

A query graph is the subgraph that is being seached for in the target graph.

matches are label similarities between nodes in the query graph and target graph with a weight where \(0 \lt weight \lt= 1\). Users are free to caculate label similarity scores however they like. Fornax only needs to know about non zero weights between matches.

Once a query has been created and executed it will return the n subgraphs in the target graph which are most similar to the query graph based on the similarity score between nodes and their surrounding neighbourhoods.

Note

Nodes in the target graph will only be returned from a query if they have a non zero similarity score to at least one node in the query graph.

class fornax.api.QueryHandle(connection: fornax.api.Connection, query_id: int)[source]

Create a handle to an existing query via connection with unique id query_id.

Parameters:
  • connection (Connection) – a fornax database connection
  • query_id (int) – unique id for an existing query
add_matches(sources: Iterable[int], targets: Iterable[int], weights: Iterable[float], **kwargs)[source]

Add matches between the query graph and the target graph

Parameters:
  • sources (typing.Iterable[int]) – Iterable of src_id in the query graph
  • targets (typing.Iterable[int]) – Iterable of src_id in the target graph
  • weights (typing.Iterable[float]) – Iterable of weights between 0 and 1

For example, to add matches between

  • node 0 in the query graph and node 0 in the target graph with weight .9
  • node 0 in the query graph and node 1 in the target graph with weight .1

then:

query.add_matches([0, 0], [0, 1], [.9, .1])

Note

Adding weights that compare equal to zero will raise an exception.

classmethod create(connection: fornax.api.Connection, query_graph: fornax.api.GraphHandle, target_graph: fornax.api.GraphHandle)[source]

Create a new query and return a QueryHandle for it

Parameters:
  • connection (Connection) – a fornax database connection
  • query_graph (GraphHandle) – subgraph to find target graph
  • target_graph (GraphHandle) – Graph to be searched
Returns:

new QueryHandle

Return type:

QueryHandle

delete()[source]

Delete this query and any associated matches

execute(n=5, hopping_distance=2, max_iters=10)[source]

Execute a fuzzy subgraph matching query finding the top n subgraph matches between the query graph and the target graph.

Parameters:
  • n (int, optional) – number of subgraph matches to return
  • hopping_distance (int, optional) – lengthscale hyperparameter, defaults to 2
  • max_iters (int, optional) – maximum number of optimisation iterations
Returns:

query result

Return type:

dict

query_graph() → fornax.api.GraphHandle[source]

Get a QueryHandle for the query graph

Returns:query graph
Return type:GraphHandle
classmethod read(connection: fornax.api.Connection, query_id: int)[source]

Create a new QueryHandle to an existing query with unique id query_id via connection.

Parameters:
  • connection (Connection) – a fornax database connection
  • query_id (int) – unique identifier for a query
Returns:

new QueryHandle

Return type:

QueryHandle

target_graph() → fornax.api.GraphHandle[source]

Get a QueryHandle for the target graph

Returns:target graph
Return type:GraphHandle