Skip to content

This feature is currently in Preview.

Run a Graph Algorithm

To use a graph algorithm to calculate a property in your model, first define the graph and call the Graph object’s method for the algorithm you want to use Then deploy the model and query the results in Snowflake.

In the following example, the .degree() method is used to count how many other accounts each account in a payment graph exchanges payments with.

The model has four accounts. Account 1 pays account 2 twice, account 2 pays account 3, and account 4 has no payments. Account 2 also pays itself.

  1. Define the model and graph algorithm.

    Consider the following model of accounts and payments:

    from relationalai.semantics import Integer, Model
    from relationalai.semantics.reasoners.graph import Graph
    m = Model("AccountCounterparties")
    Account = m.Concept("Account", identify_by={"id": Integer})
    Payment = m.Concept("Payment", identify_by={"id": Integer})
    Payment.payer = m.Property(f"{Payment} sent from {Account:payer}")
    Payment.payee = m.Property(f"{Payment} sent to {Account:payee}")
    Account.counterparty_count = m.Property(
    f"{Account} has {Integer:counterparty_count} counterparties"
    )
    21 collapsed lines
    account_data = m.data([
    {"id": 1},
    {"id": 2},
    {"id": 3},
    {"id": 4},
    ])
    m.define(Account.new(account_data.to_schema()))
    payment_data = m.data([
    {"id": 100, "payer_id": 1, "payee_id": 2},
    {"id": 101, "payer_id": 1, "payee_id": 2},
    {"id": 102, "payer_id": 2, "payee_id": 3},
    {"id": 103, "payer_id": 2, "payee_id": 2},
    ])
    m.define(
    Payment.new(
    id=payment_data.id,
    payer=Account.lookup(id=payment_data.payer_id),
    payee=Account.lookup(id=payment_data.payee_id),
    )
    )
    graph = Graph(
    m,
    directed=False,
    weighted=False,
    aggregator="sum",
    node_concept=Account,
    )
    m.where(Payment.payer != Payment.payee).define(
    graph.Edge.new(
    id=Payment.id,
    src=Payment.payer,
    dst=Payment.payee,
    )
    )
    degree = graph.degree()
    m.where(degree(Account, Integer)).define(
    Account.counterparty_count(Integer)
    )
    • node_concept=Account makes every account a node, even account 4, which has no payments.
    • id=Payment.id gives each payment its own edge. aggregator="sum" combines edges between the same two accounts. Since the graph is unweighted, it counts each connection once, not each payment.
    • Payment.payer != Payment.payee leaves out payments an account makes to itself.
    • graph.degree() defines each node’s degree: the number of connections it has. In this graph, that is the number of other accounts it exchanges payments with.
    • The final rule sets Account.counterparty_count to the degree. After deployment, this property is a column in the ACCOUNT output.
  2. Query the account counts in Snowflake.

    After you have deployed the model, you can query the account counts in Snowflake. Wait for the model’s refresh to finish before you query it. The refresh updates the results.

    Then you can query the COUNTERPARTY_COUNT column of the ACCOUNT output table:

    SELECT ID, COUNTERPARTY_COUNT
    FROM MY_DATABASE.MY_MODEL.ACCOUNT
    ORDER BY ID;
    Output
    ID COUNTERPARTY_COUNT
    1 1
    2 2
    3 1
    4 0

    Account 2 has two counterparties: accounts 1 and 3. Its two payments from account 1 count as one connection. Its payment to itself does not count. Account 4 has no payments, so its count is zero.

The following tables describe all of the algorithms available to run on PyRel Graph objects, organized by category.

AlgorithmDescription
.num_nodes()Returns a unary relationship containing the number of nodes in the graph.
.num_edges()Returns a unary relationship containing the number of edges in the graph.
.num_triangles()Returns a unary relationship containing the total number of unique triangles in the graph.
AlgorithmDescription
.neighbor()Returns a binary relationship containing all neighbor pairs in the graph.
.inneighbor()Returns a binary relationship of all nodes and their in-neighbors.
.outneighbor()Returns a binary relationship of all nodes and their out-neighbors.
.common_neighbor()Returns a ternary relationship of common neighbor triplets.
AlgorithmDescription
.degree()Returns a binary relationship containing the degree of each node. Self-loops count twice.
.indegree()Returns a binary relationship containing the indegree of each node.
.outdegree()Returns a binary relationship containing the outdegree of each node.
.weighted_degree()Returns a binary relationship containing the weighted degree of each node. Self-loops count twice.
.weighted_indegree()Returns a binary relationship containing the weighted indegree of each node.
.weighted_outdegree()Returns a binary relationship containing the weighted outdegree of each node.
AlgorithmDescription
.degree_centrality()Returns a binary relationship containing the degree centrality of each node.
.eigenvector_centrality()Returns a binary relationship containing the eigenvector centrality of each node.
.betweenness_centrality()Returns a binary relationship containing the betweenness centrality of each node.
.pagerank()Returns a binary relationship containing the PageRank score of each node.
AlgorithmDescription
.jaccard_similarity()Returns a ternary relationship containing the Jaccard similarity for pairs of nodes.
.cosine_similarity()Returns a ternary relationship containing the cosine similarity for pairs of nodes.
AlgorithmDescription
.adamic_adar()Returns a ternary relationship containing the Adamic-Adar index for pairs of nodes.
.preferential_attachment()Returns a ternary relationship containing the preferential attachment score for pairs of nodes.
AlgorithmDescription
.infomap()Partitions nodes into communities using a variant of the Infomap algorithm.
.louvain()Partitions nodes into communities using the Louvain algorithm.
.label_propagation()Partitions nodes into communities using the Label Propagation algorithm.
AlgorithmDescription
.triangle()Returns a ternary relationship containing all triangles in the graph.
.unique_triangle()Returns a ternary relationship containing all unique triangles in the graph.
.triangle_count()Returns a binary relationship containing the number of unique triangles each node belongs to.
.local_clustering_coefficient()Returns a binary relationship containing the local clustering coefficient of each node.
.average_clustering_coefficient()Returns a unary relationship containing the average clustering coefficient of the graph.
AlgorithmDescription
.reachable()Returns a binary relationship of pairs of nodes (u, v) where v is reachable from u.
.weakly_connected_component()Returns a binary relationship that maps each node to its weakly connected component.
.is_connected()Returns a unary relationship containing whether the graph is connected.

To find paths that match a specific pattern, or to get the paths themselves (the sequence of nodes and edges), see Path reasoning.

AlgorithmDescription
.distance()Returns a ternary relationship containing the shortest path length between pairs of nodes.
.diameter_range()Estimates the graph diameter and returns it as a minimum and maximum bound. Not available for directed or weighted graphs.