Skip to content

Commit

Permalink
refactor path struct out of graph.rs, add request_handler module
Browse files Browse the repository at this point in the history
  • Loading branch information
kyzooghost committed Sep 28, 2024

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
1 parent a41fc1b commit bdecba1
Showing 11 changed files with 422 additions and 2,725 deletions.
2,750 changes: 187 additions & 2,563 deletions Cargo.lock

Large diffs are not rendered by default.

3 changes: 1 addition & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
[workspace]
members = [
"adaptors",
"app",
"arbitrage_engine"
]
, "request_handler/request_handler"]
22 changes: 20 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -4,10 +4,28 @@ WIP.

Modules
- Core arbitrage engine
- Adaptors for each network and protocol
- (Deprecated) Adaptors for each network and protocol

Useful CLI commands
# Goal

Hold graph data structure in memory. Receive messages from another program to
i.) Update graph data structure
ii.) Run arbitrage-scan algorithm on in-memory data structure, return discovered arbitrages

Can model as request-response endpoints

API:
- add_node<T, T>
- add_edge<T, f64>(T, T, f64)
- get_negative_cycle_quick

# TODO

Loop in main.rs that waits on messages from another process
Handler for external process messages
-> API for arbitrage_engine

# CLI commands

Run unit tests without silencing stdout

9 changes: 5 additions & 4 deletions app/src/main.rs
Original file line number Diff line number Diff line change
@@ -6,9 +6,10 @@ use eyre::Result;
#[tokio::main]
async fn main() -> Result<()> {
println!("Hello, world");
// let mut a: Vec<Vec<usize>> = Vec::new();
// a.push(Vec::new());
// println!("{:?}", a[0]);
// println!("{:?}", a[1]);

// TODO - Set up loop that listens for messages from external process
// external_request_handler component, with interface and specific implementation
// external_request_handler.listen

Ok(())
}
155 changes: 2 additions & 153 deletions arbitrage_engine/src/graph.rs
Original file line number Diff line number Diff line change
@@ -11,170 +11,19 @@ mod graph_mod {
};

use super::super::utils::logger::{logObject, logText};

#[test]
fn petgraph_basic_methods() {
let mut graph: Graph<&str, f64> = Graph::new();
let origin = graph.add_node("Denver");
let destination_1 = graph.add_node("San Diego");
let destination_2 = graph.add_node("New York");
let cost_1 = graph.add_edge(origin, destination_1, 250.0);
let cost_2 = graph.add_edge(origin, destination_2, 1099.0);
assert_eq!(graph.node_weight(origin).unwrap(), &"Denver");
assert_eq!(graph[destination_1], "San Diego");
assert_eq!(graph.edge_weight(cost_1).unwrap(), &250.0);
assert_eq!(graph.edge_weight(cost_2).unwrap(), &1099.0);
*graph.edge_weight_mut(cost_1).unwrap() = 249.0;
assert_eq!(graph.edge_weight(cost_1).unwrap(), &249.0);
}

pub mod path {
use super::{EdgeIndex, Graph, NodeIndex};
use std::{
marker::PhantomData,
cmp::Ordering
};

// Choosing to store vector of indexes, rather than using a recursive type as we did in Java. Should be ok if the vectors don't grow too large.
#[derive(Debug)]
pub struct Path<N: Clone> {
weight: f64,
edges: Vec<EdgeIndex>,
nodes: Vec<NodeIndex>,
node_type: PhantomData<N>,
}

impl<N: Clone> Path<N> {
pub fn new(source_node: NodeIndex) -> Self {
Path {
weight: 0.0_f64,
edges: Vec::new(),
nodes: vec![source_node],
node_type: PhantomData,
}
}

pub fn add_to_path(&mut self, graph: &Graph<N, f64>, edge: EdgeIndex) {
assert_eq!(
&graph.edge_endpoints(edge).unwrap().0,
self.nodes.last().unwrap(),
"Edge does not extend from existing path"
);
self.weight += graph.edge_weight(edge).unwrap();
self.edges.push(edge);
self.nodes.push(graph.edge_endpoints(edge).unwrap().1);
}

pub fn weight(&self) -> f64 {
self.weight
}

pub fn edges(&self) -> Vec<EdgeIndex> {
let mut vec: Vec<EdgeIndex> = Vec::new();
for edge in self.edges.iter() {
vec.push(*edge);
}
vec
}

pub fn nodes(&self) -> Vec<NodeIndex> {
let mut vec: Vec<NodeIndex> = Vec::new();
for node in self.nodes.iter() {
vec.push(*node);
}
vec
}

pub fn length(&self) -> usize {
self.nodes.len()
}
}

impl<N: Clone> PartialEq for Path<N> {
fn eq(&self, other: &Self) -> bool {
self.weight.to_bits() == other.weight.to_bits()
}
}

impl<N: Clone> Eq for Path<N> {}

impl<N: Clone> PartialOrd for Path<N> {
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
Some(self.cmp(other))
}
}

impl<N: Clone> Ord for Path<N> {
fn cmp(&self, other: &Self) -> Ordering {
if self.weight < other.weight {
Ordering::Less
} else if self.weight > other.weight {
Ordering::Greater
} else {
Ordering::Equal
}
}
}

#[test]
fn path_basic_methods() {
// Build graph
let mut graph: Graph<&str, f64> = Graph::new();
let origin = graph.add_node("Denver");
let destination_1 = graph.add_node("San Diego");
let destination_2 = graph.add_node("New York");
let cost_1 = graph.add_edge(origin, destination_1, 250.0);
let cost_2 = graph.add_edge(origin, destination_2, 1099.0);

// Create path
let mut path: Path<&str> = Path::new(origin);
assert_eq!(path.weight(), 0.0);
assert_eq!(path.length(), 1);
assert_eq!(path.edges().len(), 0);
assert_eq!(path.nodes().len(), 1);
assert_eq!(path.nodes()[0], origin);

// Add to path
path.add_to_path(&graph, cost_1);
assert_eq!(path.weight(), 250.0);
assert_eq!(path.length(), 2);
assert_eq!(path.edges().len(), 1);
assert_eq!(path.nodes().len(), 2);
assert_eq!(path.nodes()[0], origin);
assert_eq!(path.nodes()[1], destination_1);
assert_eq!(path.edges()[0], cost_1);

// Create another path
let mut path1: Path<&str> = Path::new(origin);
assert_eq!(path1.weight(), 0.0);
assert_eq!(path1.length(), 1);
assert_eq!(path1.edges().len(), 0);
assert_eq!(path1.nodes().len(), 1);
assert_eq!(path1.nodes()[0], origin);

// Add to another path
path1.add_to_path(&graph, cost_2);
assert_eq!(path1.weight(), 1099.0);
assert_eq!(path1.length(), 2);
assert_eq!(path1.edges().len(), 1);
assert_eq!(path1.nodes().len(), 2);
assert_eq!(path1.nodes()[0], origin);
assert_eq!(path1.nodes()[1], destination_2);
assert_eq!(path1.edges()[0], cost_2);
}
}
use super::super::path::path::Path;

pub mod cycle {
use super::{
logObject,
logText,
path::Path,
EdgeIndex,
EdgeRef,
EdgeReference,
Graph,
NodeIndex,
Outgoing,
Path
};

use std::{
3 changes: 2 additions & 1 deletion arbitrage_engine/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
pub mod graph;
pub mod utils;
pub mod utils;
pub mod path;
143 changes: 143 additions & 0 deletions arbitrage_engine/src/path.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,143 @@
pub use path_mod::*;

mod path_mod {
pub mod path {
use petgraph::{
graph::Graph,
prelude::{EdgeIndex, NodeIndex},
};

use std::{
marker::PhantomData,
cmp::Ordering
};

// Choosing to store vector of indexes, rather than using a recursive type as we did in Java. Should be ok if the vectors don't grow too large.
#[derive(Debug)]
pub struct Path<N: Clone> {
weight: f64,
edges: Vec<EdgeIndex>,
nodes: Vec<NodeIndex>,
node_type: PhantomData<N>,
}

impl<N: Clone> Path<N> {
pub fn new(source_node: NodeIndex) -> Self {
Path {
weight: 0.0_f64,
edges: Vec::new(),
nodes: vec![source_node],
node_type: PhantomData,
}
}

pub fn add_to_path(&mut self, graph: &Graph<N, f64>, edge: EdgeIndex) {
assert_eq!(
&graph.edge_endpoints(edge).unwrap().0,
self.nodes.last().unwrap(),
"Edge does not extend from existing path"
);
self.weight += graph.edge_weight(edge).unwrap();
self.edges.push(edge);
self.nodes.push(graph.edge_endpoints(edge).unwrap().1);
}

pub fn weight(&self) -> f64 {
self.weight
}

pub fn edges(&self) -> Vec<EdgeIndex> {
let mut vec: Vec<EdgeIndex> = Vec::new();
for edge in self.edges.iter() {
vec.push(*edge);
}
vec
}

pub fn nodes(&self) -> Vec<NodeIndex> {
let mut vec: Vec<NodeIndex> = Vec::new();
for node in self.nodes.iter() {
vec.push(*node);
}
vec
}

pub fn length(&self) -> usize {
self.nodes.len()
}
}

impl<N: Clone> PartialEq for Path<N> {
fn eq(&self, other: &Self) -> bool {
self.weight.to_bits() == other.weight.to_bits()
}
}

impl<N: Clone> Eq for Path<N> {}

impl<N: Clone> PartialOrd for Path<N> {
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
Some(self.cmp(other))
}
}

impl<N: Clone> Ord for Path<N> {
fn cmp(&self, other: &Self) -> Ordering {
if self.weight < other.weight {
Ordering::Less
} else if self.weight > other.weight {
Ordering::Greater
} else {
Ordering::Equal
}
}
}

#[test]
fn path_basic_methods() {
// Build graph
let mut graph: Graph<&str, f64> = Graph::new();
let origin = graph.add_node("Denver");
let destination_1 = graph.add_node("San Diego");
let destination_2 = graph.add_node("New York");
let cost_1 = graph.add_edge(origin, destination_1, 250.0);
let cost_2 = graph.add_edge(origin, destination_2, 1099.0);

// Create path
let mut path: Path<&str> = Path::new(origin);
assert_eq!(path.weight(), 0.0);
assert_eq!(path.length(), 1);
assert_eq!(path.edges().len(), 0);
assert_eq!(path.nodes().len(), 1);
assert_eq!(path.nodes()[0], origin);

// Add to path
path.add_to_path(&graph, cost_1);
assert_eq!(path.weight(), 250.0);
assert_eq!(path.length(), 2);
assert_eq!(path.edges().len(), 1);
assert_eq!(path.nodes().len(), 2);
assert_eq!(path.nodes()[0], origin);
assert_eq!(path.nodes()[1], destination_1);
assert_eq!(path.edges()[0], cost_1);

// Create another path
let mut path1: Path<&str> = Path::new(origin);
assert_eq!(path1.weight(), 0.0);
assert_eq!(path1.length(), 1);
assert_eq!(path1.edges().len(), 0);
assert_eq!(path1.nodes().len(), 1);
assert_eq!(path1.nodes()[0], origin);

// Add to another path
path1.add_to_path(&graph, cost_2);
assert_eq!(path1.weight(), 1099.0);
assert_eq!(path1.length(), 2);
assert_eq!(path1.edges().len(), 1);
assert_eq!(path1.nodes().len(), 2);
assert_eq!(path1.nodes()[0], origin);
assert_eq!(path1.nodes()[1], destination_2);
assert_eq!(path1.edges()[0], cost_2);
}
}
}
17 changes: 17 additions & 0 deletions petgraph-tute.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
```rust
#[test]
fn petgraph_basic_methods() {
let mut graph: Graph<&str, f64> = Graph::new();
let origin = graph.add_node("Denver");
let destination_1 = graph.add_node("San Diego");
let destination_2 = graph.add_node("New York");
let cost_1 = graph.add_edge(origin, destination_1, 250.0);
let cost_2 = graph.add_edge(origin, destination_2, 1099.0);
assert_eq!(graph.node_weight(origin).unwrap(), &"Denver");
assert_eq!(graph[destination_1], "San Diego");
assert_eq!(graph.edge_weight(cost_1).unwrap(), &250.0);
assert_eq!(graph.edge_weight(cost_2).unwrap(), &1099.0);
*graph.edge_weight_mut(cost_1).unwrap() = 249.0;
assert_eq!(graph.edge_weight(cost_1).unwrap(), &249.0);
}
```
Loading

0 comments on commit bdecba1

Please sign in to comment.