Search code examples
rustborrow-checkerpetgraph

How can I remove all of the outgoing edges for a given node in a GraphMap?


I would like to know how to remove all of the outgoing edges for a given node in a directed GraphMap.

I've tried this:

use petgraph::{graphmap::GraphMap, visit::EdgeRef, Directed, Direction};
fn main() {
    let mut g = GraphMap::<MyNode, u32, Directed>::new();  
    let node1 = MyNode { value1: 1, value2: 1 };
    let node2 = MyNode { value1: 2, value2: 2 };

    g.add_node(node1);
    g.add_node(node2);
    g.add_edge(node1, node2, 1);
    
    g.edges_directed(node1, Direction::Outgoing).for_each(|edge| {
        g.remove_edge(edge.source(), edge.target());
    });      

    println!("{:?}", g);
}

#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct MyNode {
    pub value1: u32,
    pub value2: u32,
}

It wont compile with..

   Compiling playground v0.0.1 (/playground)
error[E0502]: cannot borrow `g` as mutable because it is also borrowed as immutable
  --> src/main.rs:11:59
   |
11 |     g.edges_directed(node1, Direction::Outgoing).for_each(|edge| {
   |     -                                            -------- ^^^^^^ mutable borrow occurs here
   |     |                                            |
   |     immutable borrow occurs here                 immutable borrow later used by call
12 |         g.remove_edge(edge.source(), edge.target());
   |         - second borrow occurs due to use of `g` in closure

Playground


Solution

  • The iterator that edges_directed() returns borrows from the graph, but the node IDs themselves not, so the simplest way is to collect the iterator:

    let edges_to_remove = g
        .edges_directed(node1, Direction::Outgoing)
        .map(|(source, dest, _)| (source, dest))
        .collect::<Vec<_>>();
    for (source, dest) in edges_to_remove {
        g.remove_edge(source, dest);
    }