Skip to content

Commit

Permalink
sum weight algorithm + min/max/mean/median/average/count/len/sum feat…
Browse files Browse the repository at this point in the history
…ures on edge properties (#1200)

* sum weight for a vertex algorithm

* add in out and both

* yugioh mode, implement pydirection, implement python algorithm + tests

* add docs for python algo

* implemented many functions upon the list, listlist, pyiterable, sum, count,

* fixed getter for edges with small annotation, added sum for valuelist and valuelistlist, fixed internal error with empty result, fixed none appearing in empty lists when doing a sum

* added more

* median

* remove median temporarily

* lighter algorithms

* fixed balance to be temporal

* whats done is done

* no more unwrap explosions

* add min and max vaue and keys

* min max key and value for algo result

* add min, max, mean, average to propiterable

* add min, max, mean, average, median, count, len to PyPropHistValueList + python tests

* move test to its own code

* add len, count, min, max to PyPropValueList + tests

* added average + mean to PyPropValueList + tests

* add len, count, min, max, mean, avg, median to PyPropValueList
 List+ tests

* added len, count, min, max, mean, avg, median to PyTemporalProp+ tests

* idk blank lines?

* in algo result min max median now return a k,v pair option
  • Loading branch information
Haaroon authored Sep 5, 2023
1 parent 911090a commit 47d9b63
Show file tree
Hide file tree
Showing 12 changed files with 1,216 additions and 47 deletions.
5 changes: 4 additions & 1 deletion python/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use pyo3::prelude::*;
use raphtory_core::python::{
graph::{
algorithm_result::AlgorithmResultStrU64,
edge::{PyEdge, PyEdges},
edge::{PyDirection, PyEdge, PyEdges},
graph::PyGraph,
graph_with_deletions::PyGraphWithDeletions,
properties::{PyConstProperties, PyProperties, PyTemporalProp, PyTemporalProperties},
Expand All @@ -29,6 +29,7 @@ fn raphtory(py: Python<'_>, m: &PyModule) -> PyResult<()> {
m.add_class::<PyConstProperties>()?;
m.add_class::<PyTemporalProperties>()?;
m.add_class::<PyTemporalProp>()?;
m.add_class::<PyDirection>()?;

//GRAPHQL
let graphql_module = PyModule::new(py, "internal_graphql")?;
Expand Down Expand Up @@ -80,6 +81,8 @@ fn raphtory(py: Python<'_>, m: &PyModule) -> PyResult<()> {
algorithm_module
)?)?;
algorithm_module.add_function(wrap_pyfunction!(hits, algorithm_module)?)?;
algorithm_module.add_function(wrap_pyfunction!(balance, algorithm_module)?)?;

m.add_submodule(algorithm_module)?;

//GRAPH LOADER
Expand Down
116 changes: 83 additions & 33 deletions python/tests/test_graphdb.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
import pandas as pd
import pandas.core.frame
import pytest
from raphtory import Graph, GraphWithDeletions
from raphtory import Graph, GraphWithDeletions, PyDirection
from raphtory import algorithms
from raphtory import graph_loader
import tempfile
Expand Down Expand Up @@ -271,6 +271,7 @@ def test_getitem():

assert g.vertex(1).properties.temporal.get("cost") == g.vertex(1).properties.temporal["cost"]


def test_graph_properties():
g = create_graph()

Expand Down Expand Up @@ -1000,7 +1001,7 @@ def test_edge_history():
view = g.window(1, 5)

assert (g.edge(1, 2).history() == [1, 3])
assert(view.edge(1, 4).history() == [4])
assert (view.edge(1, 4).history() == [4])


def test_lotr_edge_history():
Expand Down Expand Up @@ -1418,7 +1419,6 @@ def test_deletions():
assert list(g.edge(edges[0][1], edges[0][2]).explode().latest_time()) == [10]



def test_load_from_pandas():
import pandas as pd
df = pd.DataFrame({
Expand Down Expand Up @@ -1525,60 +1525,87 @@ def test_load_from_pandas_with_types():
"weight": [1.0, 2.0, 3.0, 4.0, 5.0],
"marbles": ["red", "blue", "green", "yellow", "purple"],
"marbles_const": ["red", "blue", "green", "yellow", "purple"],
"layers": ["layer 1", "layer 2", "layer 3", "layer 4", "layer 5"]
"layers": ["layer 1", "layer 2", "layer 3", "layer 4", "layer 5"]
})
vertices_df = pd.DataFrame({
"id": [1, 2, 3, 4, 5, 6],
"name": ["Alice", "Bob", "Carol", "Dave", "Eve", "Frank"],
"time": [1, 2, 3, 4, 5, 6],
"type": ["Person 1", "Person 2", "Person 3", "Person 4", "Person 5", "Person 6"]
"type": ["Person 1", "Person 2", "Person 3", "Person 4", "Person 5", "Person 6"]
})
g = Graph()
g.load_vertices_from_pandas(vertices_df, "id", "time", ["name"],shared_const_props={"type": "Person", "tag": "test_tag"})
assert g.vertices().properties.constant.get("type").collect() == ["Person", "Person", "Person", "Person", "Person", "Person"]
assert g.vertices().properties.constant.get("tag").collect() == ["test_tag", "test_tag", "test_tag", "test_tag", "test_tag", "test_tag"]
g.load_vertices_from_pandas(vertices_df, "id", "time", ["name"],
shared_const_props={"type": "Person", "tag": "test_tag"})
assert g.vertices().properties.constant.get("type").collect() == ["Person", "Person", "Person", "Person", "Person",
"Person"]
assert g.vertices().properties.constant.get("tag").collect() == ["test_tag", "test_tag", "test_tag", "test_tag",
"test_tag", "test_tag"]

g = Graph()
g.load_vertices_from_pandas(vertices_df, "id", "time", ["name"],const_props=["type"])
assert g.vertices().properties.constant.get("type").collect() == ["Person 1", "Person 2", "Person 3", "Person 4", "Person 5", "Person 6"]
g.load_vertices_from_pandas(vertices_df, "id", "time", ["name"], const_props=["type"])
assert g.vertices().properties.constant.get("type").collect() == ["Person 1", "Person 2", "Person 3", "Person 4",
"Person 5", "Person 6"]

g = Graph()
g.load_edges_from_pandas(edges_df, "src", "dst", "time", ["weight", "marbles"], const_props=["marbles_const"], shared_const_props={"type": "Edge", "tag": "test_tag"}, layer="test_layer")
g.load_edges_from_pandas(edges_df, "src", "dst", "time", ["weight", "marbles"], const_props=["marbles_const"],
shared_const_props={"type": "Edge", "tag": "test_tag"}, layer="test_layer")

assert g.layers(["test_layer"]).edges().src().id().collect() == [1, 2, 3, 4, 5]
assert g.edges().properties.constant.get("type").collect() == [{'test_layer': 'Edge'},{'test_layer': 'Edge'},{'test_layer': 'Edge'},{'test_layer': 'Edge'},{'test_layer': 'Edge'}]
assert g.edges().properties.constant.get("tag").collect() == [{'test_layer': 'test_tag'},{'test_layer': 'test_tag'},{'test_layer': 'test_tag'},{'test_layer': 'test_tag'},{'test_layer': 'test_tag'}]
assert g.edges().properties.constant.get("marbles_const").collect() == [{'test_layer': 'red'},{'test_layer': 'blue'},{'test_layer': 'green'},{'test_layer': 'yellow'},{'test_layer': 'purple'}]

assert g.edges().properties.constant.get("type").collect() == [{'test_layer': 'Edge'}, {'test_layer': 'Edge'},
{'test_layer': 'Edge'}, {'test_layer': 'Edge'},
{'test_layer': 'Edge'}]
assert g.edges().properties.constant.get("tag").collect() == [{'test_layer': 'test_tag'},
{'test_layer': 'test_tag'},
{'test_layer': 'test_tag'},
{'test_layer': 'test_tag'},
{'test_layer': 'test_tag'}]
assert g.edges().properties.constant.get("marbles_const").collect() == [{'test_layer': 'red'},
{'test_layer': 'blue'},
{'test_layer': 'green'},
{'test_layer': 'yellow'},
{'test_layer': 'purple'}]

g = Graph()
g.load_edges_from_pandas(edges_df, "src", "dst", "time", ["weight", "marbles"],layer_in_df="layers")
g.load_edges_from_pandas(edges_df, "src", "dst", "time", ["weight", "marbles"], layer_in_df="layers")
assert g.layers(["layer 1"]).edges().src().id().collect() == [1]
assert g.layers(["layer 1","layer 2"]).edges().src().id().collect() == [1,2]
assert g.layers(["layer 1","layer 2","layer 3"]).edges().src().id().collect() == [1,2,3]
assert g.layers(["layer 1","layer 4","layer 5"]).edges().src().id().collect() == [1,4,5]

g = Graph.load_from_pandas(edges_df, "src", "dst", "time", layer = "test_layer",vertex_df=vertices_df, vertex_col="id", vertex_time_col="time", vertex_props=["name"],vertex_shared_const_props={"type":"Person"})
assert g.vertices().properties.constant.get("type").collect() == ["Person", "Person", "Person", "Person", "Person", "Person"]
assert g.layers(["layer 1", "layer 2"]).edges().src().id().collect() == [1, 2]
assert g.layers(["layer 1", "layer 2", "layer 3"]).edges().src().id().collect() == [1, 2, 3]
assert g.layers(["layer 1", "layer 4", "layer 5"]).edges().src().id().collect() == [1, 4, 5]

g = Graph.load_from_pandas(edges_df, "src", "dst", "time", layer="test_layer", vertex_df=vertices_df,
vertex_col="id", vertex_time_col="time", vertex_props=["name"],
vertex_shared_const_props={"type": "Person"})
assert g.vertices().properties.constant.get("type").collect() == ["Person", "Person", "Person", "Person", "Person",
"Person"]
assert g.layers(["test_layer"]).edges().src().id().collect() == [1, 2, 3, 4, 5]

g = Graph.load_from_pandas(edges_df, "src", "dst", "time", layer_in_df = "layers",vertex_df=vertices_df, vertex_col="id", vertex_time_col="time", vertex_props=["name"],vertex_const_props=["type"])
assert g.vertices().properties.constant.get("type").collect() == ["Person 1", "Person 2", "Person 3", "Person 4", "Person 5", "Person 6"]
g = Graph.load_from_pandas(edges_df, "src", "dst", "time", layer_in_df="layers", vertex_df=vertices_df,
vertex_col="id", vertex_time_col="time", vertex_props=["name"],
vertex_const_props=["type"])
assert g.vertices().properties.constant.get("type").collect() == ["Person 1", "Person 2", "Person 3", "Person 4",
"Person 5", "Person 6"]
assert g.layers(["layer 1"]).edges().src().id().collect() == [1]
assert g.layers(["layer 1","layer 2"]).edges().src().id().collect() == [1,2]
assert g.layers(["layer 1","layer 2","layer 3"]).edges().src().id().collect() == [1,2,3]
assert g.layers(["layer 1","layer 4","layer 5"]).edges().src().id().collect() == [1,4,5]
assert g.layers(["layer 1", "layer 2"]).edges().src().id().collect() == [1, 2]
assert g.layers(["layer 1", "layer 2", "layer 3"]).edges().src().id().collect() == [1, 2, 3]
assert g.layers(["layer 1", "layer 4", "layer 5"]).edges().src().id().collect() == [1, 4, 5]

g = Graph.load_from_pandas(edges_df, src="src", dst="dst", time="time", props=["weight", "marbles"],
vertex_df=vertices_df, vertex_col="id", vertex_time_col="time", vertex_props=["name"],layer_in_df="layers")
vertex_df=vertices_df, vertex_col="id", vertex_time_col="time", vertex_props=["name"],
layer_in_df="layers")

g.load_vertex_props_from_pandas(vertices_df, "id", const_props=["type"], shared_const_props={"tag": "test_tag"})
assert g.vertices().properties.constant.get("type").collect() == ["Person 1", "Person 2", "Person 3", "Person 4", "Person 5", "Person 6"]
assert g.vertices().properties.constant.get("tag").collect() == ["test_tag", "test_tag", "test_tag", "test_tag", "test_tag", "test_tag"]
assert g.vertices().properties.constant.get("type").collect() == ["Person 1", "Person 2", "Person 3", "Person 4",
"Person 5", "Person 6"]
assert g.vertices().properties.constant.get("tag").collect() == ["test_tag", "test_tag", "test_tag", "test_tag",
"test_tag", "test_tag"]

g.load_edge_props_from_pandas(edges_df, "src", "dst", const_props=["marbles_const"], shared_const_props={"tag": "test_tag"},layer_in_df="layers")
assert g.layers(["layer 1", "layer 2", "layer 3"]).edges().properties.constant.get("marbles_const").collect() == [{'layer 1': 'red'}, {'layer 2': 'blue'}, {'layer 3': 'green'}]
assert g.edges().properties.constant.get("tag").collect() == [{'layer 1': 'test_tag'}, {'layer 2': 'test_tag'}, {'layer 3': 'test_tag'}, {'layer 4': 'test_tag'}, {'layer 5': 'test_tag'}]
g.load_edge_props_from_pandas(edges_df, "src", "dst", const_props=["marbles_const"],
shared_const_props={"tag": "test_tag"}, layer_in_df="layers")
assert g.layers(["layer 1", "layer 2", "layer 3"]).edges().properties.constant.get("marbles_const").collect() == [
{'layer 1': 'red'}, {'layer 2': 'blue'}, {'layer 3': 'green'}]
assert g.edges().properties.constant.get("tag").collect() == [{'layer 1': 'test_tag'}, {'layer 2': 'test_tag'},
{'layer 3': 'test_tag'}, {'layer 4': 'test_tag'},
{'layer 5': 'test_tag'}]


def test_edge_layer():
Expand All @@ -1594,3 +1621,26 @@ def test_hits_algorithm():
g = graph_loader.lotr_graph()
assert algorithms.hits(g).get('Aldor') == (0.0035840950440615416, 0.007476256228983402)


def test_balance_algorithm():
g = Graph()
edges_str = [
("1", "2", 10.0, 1),
("1", "4", 20.0, 2),
("2", "3", 5.0, 3),
("3", "2", 2.0, 4),
("3", "1", 1.0, 5),
("4", "3", 10.0, 6),
("4", "1", 5.0, 7),
("1", "5", 2.0, 8)
]
for (src, dst, val, time) in edges_str:
g.add_edge(time, src, dst, {'value_dec': val})
result = algorithms.balance(g, "value_dec", PyDirection("BOTH"), None).get_all()
assert result == {'1': -26.0, '2': 7.0, '3': 12.0, '4': 5.0, '5': 2.0}

result = algorithms.balance(g, "value_dec", PyDirection("IN"), None).get_all()
assert result == {'1': 6.0, '2': 12.0, '3': 15.0, '4': 20.0, '5': 2.0}

result = algorithms.balance(g, "value_dec", PyDirection("OUT"), None).get_all()
assert result == {'1': -32.0, '2': -5.0, '3': -3.0, '4': -15.0, '5': 0.0}
Loading

0 comments on commit 47d9b63

Please sign in to comment.