Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Mutual scores #17

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 8 additions & 8 deletions core/src/common.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,14 @@ use crate::constants::EPSILON;

pub fn sign<T>(x: T) -> i32
where
T: Into<f64> + Copy,
T: Into<f64> + Copy,
{
let x: f64 = x.into();
let x: f64 = x.into();

if x > EPSILON {
return 1;
} else if x < -EPSILON {
return -1;
}
return 0;
if x > EPSILON {
return 1;
} else if x < -EPSILON {
return -1;
}
return 0;
}
8 changes: 4 additions & 4 deletions core/src/constants.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
pub const ASSERT : bool = option_env!("MERITRANK_NO_ASSERT").is_none();
pub const VERBOSE : bool = true;
pub const OPTIMIZE_INVALIDATION : bool = true;
pub const EPSILON : f64 = 1e-6;
pub const ASSERT: bool = option_env!("MERITRANK_NO_ASSERT").is_none();
pub const VERBOSE: bool = true;
pub const OPTIMIZE_INVALIDATION: bool = true;
pub const EPSILON: f64 = 1e-6;
6 changes: 3 additions & 3 deletions core/src/counter.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use integer_hasher::IntMap;
use crate::graph::NodeId;
use tinyset::SetUsize;
use integer_hasher::IntMap;
use once_cell::sync::Lazy;
use tinyset::SetUsize;

type CounterValue = i32;

Expand Down Expand Up @@ -91,7 +91,7 @@ impl Default for &Counter {

/// Iterator over the entries of the `Counter`.
pub struct CounterIterator<'a> {
inner: std::collections::hash_map::Iter<'a, NodeId, CounterValue>,
inner: std::collections::hash_map::Iter<'a, NodeId, CounterValue>,
}

impl<'a> Iterator for CounterIterator<'a> {
Expand Down
22 changes: 11 additions & 11 deletions core/src/debug.rs
Original file line number Diff line number Diff line change
@@ -1,21 +1,21 @@
use std::fmt;
use crate::{RandomWalk, WalkStorage};
use std::fmt;

impl fmt::Debug for RandomWalk {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
// Implement the formatting logic for RandomWalk
// Here you can format the RandomWalk fields as desired
write!(f, "RandomWalk {{ nodes: {:?} }}", self.get_nodes())
}
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
// Implement the formatting logic for RandomWalk
// Here you can format the RandomWalk fields as desired
write!(f, "RandomWalk {{ nodes: {:?} }}", self.get_nodes())
}
}

impl fmt::Debug for WalkStorage {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
// Implement the formatting logic for WalkStorage
// Here you can format the storage contents as desired
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
// Implement the formatting logic for WalkStorage
// Here you can format the storage contents as desired

write!(f, "WalkStorage {{ walks: {:?} }}", self.get_walks())
}
write!(f, "WalkStorage {{ walks: {:?} }}", self.get_walks())
}
}

#[macro_export]
Expand Down
56 changes: 28 additions & 28 deletions core/src/errors.rs
Original file line number Diff line number Diff line change
@@ -1,40 +1,40 @@
/// Errors that can occur in the MeritRank implementation.
#[derive(Debug, Clone)]
pub enum MeritRankError {
ZeroWeightEncountered,
NodeDoesNotExist,
SelfReferenceNotAllowed,
RandomChoiceError,
NoPathExists,
NodeIdParseError,
NodeIsNotCalculated,
InvalidWalkLength,
NodeNotFound,
WalkNotFound,
EdgeNotFound,
ZeroWeightEncountered,
NodeDoesNotExist,
SelfReferenceNotAllowed,
RandomChoiceError,
NoPathExists,
NodeIdParseError,
NodeIsNotCalculated,
InvalidWalkLength,
NodeNotFound,
WalkNotFound,
EdgeNotFound,
}


use std::error::Error;
use std::fmt::{Display, Formatter, Result};

impl Display for MeritRankError {
fn fmt(&self, f: &mut Formatter<'_>) -> Result {
match self {
MeritRankError::ZeroWeightEncountered => write!(f, "Edge with zero weights are not allowed"),
MeritRankError::NodeDoesNotExist => write!(f, "Node does not exist"),
MeritRankError::SelfReferenceNotAllowed => write!(f, "Self-reference is not allowed"),
MeritRankError::RandomChoiceError => write!(f, "Random choice error"),
MeritRankError::NoPathExists => write!(f, "No path exists"),
MeritRankError::NodeIdParseError => write!(f, "Node ID parse error"),
MeritRankError::NodeIsNotCalculated => write!(f, "Node is not calculated"),
MeritRankError::InvalidWalkLength => write!(f, "Invalid walk length"),
MeritRankError::NodeNotFound => write!(f, "Can't find the node with the given ID"),
MeritRankError::WalkNotFound => write!(f, "Can't find the walk with the given ID"),
MeritRankError::EdgeNotFound => write!(f, "Can't find the edge between given nodes"),
fn fmt(&self, f: &mut Formatter<'_>) -> Result {
match self {
MeritRankError::ZeroWeightEncountered => {
write!(f, "Edge with zero weights are not allowed")
}
MeritRankError::NodeDoesNotExist => write!(f, "Node does not exist"),
MeritRankError::SelfReferenceNotAllowed => write!(f, "Self-reference is not allowed"),
MeritRankError::RandomChoiceError => write!(f, "Random choice error"),
MeritRankError::NoPathExists => write!(f, "No path exists"),
MeritRankError::NodeIdParseError => write!(f, "Node ID parse error"),
MeritRankError::NodeIsNotCalculated => write!(f, "Node is not calculated"),
MeritRankError::InvalidWalkLength => write!(f, "Invalid walk length"),
MeritRankError::NodeNotFound => write!(f, "Can't find the node with the given ID"),
MeritRankError::WalkNotFound => write!(f, "Can't find the walk with the given ID"),
MeritRankError::EdgeNotFound => write!(f, "Can't find the edge between given nodes"),
}
}
}
}

impl Error for MeritRankError {
}
impl Error for MeritRankError {}
70 changes: 36 additions & 34 deletions core/src/graph.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
use indexmap::IndexMap;
use integer_hasher::{BuildIntHasher};
use integer_hasher::BuildIntHasher;

use crate::errors::MeritRankError;
use crate::RandomWalk;
use log::error;
use rand::distributions::{Distribution, WeightedIndex};
use rand::{thread_rng, Rng};
use crate::errors::MeritRankError;
use crate::RandomWalk;

type IntIndexMap<K, V> = IndexMap<K, V, BuildIntHasher<K>>;

Expand Down Expand Up @@ -90,17 +90,14 @@ impl NodeData {
}
}


#[derive(Debug, Clone)]
pub struct Graph {
pub nodes: Vec<NodeData>,
}

impl Graph {
pub fn new() -> Self {
Graph {
nodes: Vec::new(),
}
Graph { nodes: Vec::new() }
}
pub fn get_new_nodeid(&mut self) -> NodeId {
self.nodes.push(NodeData::default());
Expand All @@ -113,8 +110,13 @@ impl Graph {
self.nodes.get(node_id).is_some()
}

pub fn set_edge(&mut self, from: NodeId, to: NodeId, weight: Weight) -> Result<(), MeritRankError> {
if !self.contains_node(from) || ! self.contains_node(to) {
pub fn set_edge(
&mut self,
from: NodeId,
to: NodeId,
weight: Weight,
) -> Result<(), MeritRankError> {
if !self.contains_node(from) || !self.contains_node(to) {
return Err(MeritRankError::NodeNotFound);
}
if from == to {
Expand All @@ -125,7 +127,10 @@ impl Graph {
self.remove_edge(from, to).unwrap();
}

let node = self.nodes.get_mut(from).ok_or(MeritRankError::NodeNotFound)?;
let node = self
.nodes
.get_mut(from)
.ok_or(MeritRankError::NodeNotFound)?;
match weight {
0.0 => {
return Err(MeritRankError::ZeroWeightEncountered);
Expand Down Expand Up @@ -154,7 +159,10 @@ impl Graph {

/// Removes the edge between the two given nodes from the graph.
pub fn remove_edge(&mut self, from: NodeId, to: NodeId) -> Result<Weight, MeritRankError> {
let node = self.nodes.get_mut(from).ok_or(MeritRankError::NodeNotFound)?;
let node = self
.nodes
.get_mut(from)
.ok_or(MeritRankError::NodeNotFound)?;
// This is slightly inefficient. More efficient would be to only try removing pos,
// and get to neg only if pos_weight is None. We keep it to check the invariant of
// not having both pos and neg weights for an edge simultaneously.
Expand Down Expand Up @@ -195,7 +203,7 @@ impl Graph {
if !self.contains_node(to) {
return Err(MeritRankError::NodeNotFound);
}
Ok(if let Some(weight) = node.pos_edges.get(&to){
Ok(if let Some(weight) = node.pos_edges.get(&to) {
Some(*weight)
} else if let Some(weight) = node.neg_edges.get(&to) {
Some(-*weight)
Expand All @@ -204,10 +212,12 @@ impl Graph {
})
}

pub fn generate_walk_segment(&mut self,
start_node: NodeId,
alpha: f64,
positive_only: bool) -> RandomWalk {
pub fn generate_walk_segment(
&mut self,
start_node: NodeId,
alpha: f64,
positive_only: bool,
) -> RandomWalk {
let mut node = start_node;
let mut segment = RandomWalk::new();
let mut rng = thread_rng();
Expand All @@ -227,27 +237,24 @@ impl Graph {
if rng.gen::<f64>() > alpha {
break;
}
if let Some((next_step, step_is_positive)) = node_data
.random_neighbor(negative_continuation_mode || positive_only){
if let Some((next_step, step_is_positive)) =
node_data.random_neighbor(negative_continuation_mode || positive_only)
{
segment.push(next_step, step_is_positive);
if !step_is_positive {
assert!(!negative_continuation_mode);
negative_continuation_mode = true;
}
node = next_step;
}else{
} else {
// Dead-end encountered
break
break;
}
}
segment
}

pub fn continue_walk(
&mut self,
walk: &mut RandomWalk,
alpha: f64,
) {
pub fn continue_walk(&mut self, walk: &mut RandomWalk, alpha: f64) {
// If the original walk is already in "negative mode",
// we should restrict segment generation to positive edges
let positive_only = walk.negative_segment_start.is_some();
Expand All @@ -257,10 +264,7 @@ impl Graph {
// Borrow mutable `walk` again for `extend`
walk.extend(&new_segment);
}
pub fn extend_walk_in_case_of_edge_deletion(
&mut self,
walk: &mut RandomWalk,
) {
pub fn extend_walk_in_case_of_edge_deletion(&mut self, walk: &mut RandomWalk) {
// Borrow mutable `walk` from `self.walks`
// No force_first_step, so this is "edge deletion mode"
//
Expand All @@ -273,12 +277,10 @@ impl Graph {
let src_node = walk.last_node().unwrap();
let node_data = self.get_node_data_mut(src_node).unwrap();
let adding_to_negative_subsegment = walk.negative_segment_start.is_some();
if let Some((forced_step, step_is_positive)) = node_data
.random_neighbor(adding_to_negative_subsegment){
if let Some((forced_step, step_is_positive)) =
node_data.random_neighbor(adding_to_negative_subsegment)
{
walk.push(forced_step, step_is_positive);
}
}

}


8 changes: 4 additions & 4 deletions core/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@ pub mod walk_storage;

pub use counter::{Counter, CounterIterator};
pub use errors::MeritRankError;
pub use graph::{Graph, NodeId, EdgeId, Weight};
pub use random_walk::RandomWalk;
pub use rank::{MeritRank};
pub use walk_storage::{WalkStorage, WalkId};
pub use graph::{EdgeId, Graph, NodeId, Weight};
pub use integer_hasher::IntMap;
pub use random_walk::RandomWalk;
pub use rank::MeritRank;
pub use walk_storage::{WalkId, WalkStorage};
Loading