rustpetgraph

Iterating over a vector gives me a different value than what is inside the vector Rust


I have been using Petgraph recently to make simple graphs with Structs for nodes and custom edges, but I have come across a problem which I am unsure if it comes from the library or Rust.

I have a graph, in which I have multiple nodes, each nodes have a name. I then put all of the index of the node (with type NodeIndex) in a vector, since Petgraph doesn't have a function to give all the nodes from a graph. I want to then create a function that given a string, it returns the index of the node that matches the name.

My problem is that somehow the type in the vector containing the nodes seems to change. I store it as NodeIndex yet the types somehow change by themselves to u32 without me changing anything. Since it changes automatically, I can't pass the values inside Petgraph functions since they require NodeIndex as inputs and not u32.

The code following is what I have so far and the problem arises in the function find_node_index_with_name where the types seem to change even though I pass a vector of NodeIndex as input so when I iterate over it, I should also get NodeIndex back.

use petgraph::adj::NodeIndex;
use petgraph::stable_graph::StableGraph;
use petgraph::dot::Dot;

#[derive(Clone,Debug,Default)]
struct ControlBloc
{
    name:String,
    value:u32,
}

fn create_bloc(name:String,value:u32) -> ControlBloc
{
    ControlBloc
    {
        name,
        value,
    }
}

fn find_node_index_with_name(gr:StableGraph<ControlBloc,u32> , nodes:Vec<NodeIndex> , name_search:String) -> Option<NodeIndex>
{
    for i in 0..nodes.len()
    {
        if gr.node_weight(nodes[i]).unwrap().name == name_search
        {
            return nodes[i];
        }
    }
    return None;
}

fn main() {
    let mut graph = StableGraph::<ControlBloc,u32>::new();
    let m = create_bloc(String::from("Main"),10);
    let b1 = create_bloc(String::from("sub1"),20);
    let b2 = create_bloc(String::from("sub2"),30);
    let main = graph.add_node(m);
    let sub1 = graph.add_node(b1);
    let sub2 = graph.add_node(b2);

    let all_nodes = vec![main,sub1,sub2];

    println!("{:?}",find_node_index_with_name(graph, all_nodes, String::from("Main")));
}

I am a bit stumped as to why the types change.

Thank you for any inputs!


Solution

  • graph.add_node() returns a petgraph::graph::NodeIndex. But you used petgraph::adj::NodeIndex which appears to be a different type (don't ask me why), thus the type mismatch.

    I took the liberty to change a bit your code in order to use references where you used owned values.

    use petgraph::graph::NodeIndex; // graph not adj
    use petgraph::stable_graph::StableGraph;
    
    #[derive(Clone, Debug, Default)]
    struct ControlBloc {
        name: String,
        value: u32,
    }
    
    fn create_bloc(
        name: String,
        value: u32,
    ) -> ControlBloc {
        ControlBloc { name, value }
    }
    
    fn find_node_index_with_name(
        gr: &StableGraph<ControlBloc, u32>,
        nodes: &[NodeIndex],
        name_search: &str,
    ) -> Option<NodeIndex> {
        nodes
            .iter()
            .map(|n| *n)
            .find(|n| gr.node_weight(*n).unwrap().name == name_search)
        /*
        for i in 0..nodes.len() {
            if gr.node_weight(nodes[i]).unwrap().name == name_search {
                return Some(nodes[i]);
            }
        }
        None
        */
    }
    
    fn main() {
        let mut graph = StableGraph::<ControlBloc, u32>::new();
        let m = create_bloc(String::from("Main"), 10);
        let b1 = create_bloc(String::from("sub1"), 20);
        let b2 = create_bloc(String::from("sub2"), 30);
        let main = graph.add_node(m);
        let sub1 = graph.add_node(b1);
        let sub2 = graph.add_node(b2);
    
        let all_nodes = vec![main, sub1, sub2];
    
        for n in ["Main", "sub1", "sub2"] {
            println!("{:?}", find_node_index_with_name(&graph, &all_nodes, n));
        }
    }
    /*
    Some(NodeIndex(0))
    Some(NodeIndex(1))
    Some(NodeIndex(2))
    */