Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/loops/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Loops 我如何变异我正在循环的结构?_Loops_Data Structures_Rust_Graph Algorithm_Borrow Checker - Fatal编程技术网

Loops 我如何变异我正在循环的结构?

Loops 我如何变异我正在循环的结构?,loops,data-structures,rust,graph-algorithm,borrow-checker,Loops,Data Structures,Rust,Graph Algorithm,Borrow Checker,这个问题的动机是 我正在使用Dijkstra的方法实现一个基本的寻路算法。它使用boundaryHashMap和finishedHashMap来保存与寻路相关的节点信息。在一个特定的循环中,我在boundary中找到值最高的节点,删除节点,将节点添加到finished,并在boundary中添加/更新节点的邻居信息 试图在其上循环时变异边界,这让Rust的借阅检查器很不舒服,但循环的逻辑对我来说似乎是合理的。我如何重写它,使编译器分享我的信心?(或者修复我丢失的错误,如果这是问题的话。) 代码:

这个问题的动机是

我正在使用Dijkstra的方法实现一个基本的寻路算法。它使用
boundary
HashMap和
finished
HashMap来保存与寻路相关的节点信息。在一个特定的循环中,我在
boundary
中找到值最高的节点,删除节点,将节点添加到
finished
,并在
boundary
中添加/更新节点的邻居信息

试图在其上循环时变异
边界
,这让Rust的借阅检查器很不舒服,但循环的逻辑对我来说似乎是合理的。我如何重写它,使编译器分享我的信心?(或者修复我丢失的错误,如果这是问题的话。)

代码:

使用std::io;
使用std::collections::{HashSet,HashMap};
使用std::cmp::Ordering;
使用std::cell::RefCell;
结构节点信息{
nbrs:HashSet,
gwlinks:i32,
}
#[推导(PartialEq,PartialOrd)]
结构PFInfo{
平均值:f32,
cum:i32,
地区:i32,
上:期权,
}
PFInfo{}的impl Eq
PFInfo请求{
fn cmp(&self,其他:&PFInfo)->订购{
匹配自身。部分_cmp(其他){
一些(ord)=>ord,
无=>排序::相等
}
}
}
类型图=HashMap;
类型PFGraph=HashMap;
//查找每行驶距离通过最多网关链接的路径,
//从给定节点开始。这是为了模拟
//“代理”,它遍历上述谜题中的图形。
fn生成路径(si:&i32,图形:&graph)->Vec{
设n=graph.len();
设mut boundary=PFGraph::具有_容量(n);
让mut finished=PFGraph::具有_容量(n);
boundary.insert(si.clone(),
PFInfo{
平均值:0。,
cum:graph.get(&si).unwrap().borrow().gwlinks,
地区:0,,
prev:None});
//继续抓取对应于最高值的键,直到找到“boundary”
//空的
而让Some((currid,)))=boundary.iter().max_by_key(|x | x.1){
//将节点从“边界”移动到“完成”`
让val=boundary.remove(&currid).unwrap();
finished.insert(currid.clone(),val);
//添加或更新未在“finished”中的所有相邻节点`
用于graph.get(&currid).unwrap()中的nbrid
.借用
.nbrs.iter()
.filter(|x |!已完成。包含_键(x)){
让currval=finished.get(&currid).unwrap();
让prev=Some(currid.clone());
设dist=currval.dist+1;
让cum=currval.cum+graph.get(nbrid.unwrap().borrow().gwlinks;
设平均值=立方米为f32/距离为f32;
边界.插入(
nbrid.clone(),
PFInfo{
平均值:平均值,
嗯:嗯,,
地区:地区,
prev:prev,
}
);
}
}
让mut path=Vec::new();
让mut currid=finished.iter().max_by_key(|x | x.1)。unwrap().0.clone();
push(currid.clone());
而让一些(previd)=完成。获取(&currid)。展开().prev{
push(previd.clone());
currid=previd.clone();
}
path.reverse();
路径
}
宏规则!解析输入{
($x:expr,$t:ident)=>($x.trim().parse::().unwrap())
}
#[测试]
fn测试_生成_路径(){
让mut inputs=“8 13 2
6 2
7 3
6 3
5 3
3 4
7 1
2 0
0 1
0 3
1 3
2 3
7 4
6 5
4.
5“。行();
让header=inputs.next().unwrap().split_whitespace().collect::();
设n=parse_input!(header[0],i32);//级别中的节点总数,包括网关
让l=parse_input!(header[1],i32);//链接数
让e=parse_input!(header[2],i32);//出口网关的数量
设mut-graph=graph::具有_容量(n为usize);
对于0..n中的节点{
insert(node,RefCell::new(NodeInfo{nbrs:HashSet::new(),gwlinks:0}));
}
设图=图;
对于0..l中的u,使用{
让link=inputs.next().unwrap();
让节点=link.split(“”).collect::();
让n1=parse_input!(节点[0],i32);//n1和N2定义这些节点之间的链接
设n2=parse_input!(节点[1],i32);
graph.get(&n1).unwrap().borrow_mut().nbrs.insert(n2);
graph.get(&n2).unwrap().borrow_mut().nbrs.insert(n1);
}
让mut gateways=HashSet::new();
对于0..e中的u作为usize{
让ei=parse_input!(inputs.next().unwrap(),i32);//网关节点的索引
网关。插入(ei);
}
让网关=网关;
用于网关中的gwid(&G){
用于&graph.get(gwid.unwrap().borrow().nbrs中的gwnbr{
(&graph).get(&gwnbr).unwrap().borrow_mut().gwlinks+=1;
}
}
断言_eq!(生成_路径(&0,&graph),vec![0,3]);
}
错误:
rustc 1.18.0(03fc9d622 2017-06-06)
错误[E0502]:无法将“boundary”借用为可变的,因为它也是借用为不可变的
--> :53:19
|
50 |而让一些((currid,|))=boundary.iter().max|u by|u key(| x | x.1){
|-----此处发生不可变借用
...
53 |让val=boundary.remove(&currid).unwrap();
|^^^^^^^^^^此处发生可变借用
...
76 |     }
|-不可变的借阅到此结束
错误[E0502]:无法将“boundary”借用为可变的,因为它也是借用为不可变的
--> :66:13
|
50 |而让一些((currid,|))=boundary.iter().max|u by|u key(| x | x.1){
|-----此处发生不可变借用
...
66 | boundary.insert(
|^^^^^^^^^^此处发生可变借用
...
76 |     }
|-不可变的借阅到此结束
错误:由于之前的两个错误而中止

我找到了一个解决我的问题的方法,它在某种程度上是可以推广的,这正是我所希望的
use std::io;
use std::collections::{HashSet, HashMap};
use std::cmp::Ordering;
use std::cell::RefCell;

struct NodeInfo {
    nbrs: HashSet<i32>,
    gwlinks: i32,
}

#[derive(PartialEq,PartialOrd)]
struct PFInfo {
    avg: f32,
    cum: i32,
    dist: i32,
    prev: Option<i32>,
}

impl Eq for PFInfo {}

impl Ord for PFInfo {
    fn cmp(&self, other: &PFInfo) -> Ordering {
       match self.partial_cmp(other) {
           Some(ord) => ord,
           None => Ordering::Equal
       }
    }
}

type Graph = HashMap<i32, RefCell<NodeInfo>>;
type PFGraph = HashMap<i32, PFInfo>;

// Find the path that passes the most gateway links per distance traveled,
// starting at a given node. This is meant to simulate the behavior of an
// "agent" which traverses the graph in the puzzle mentioned above.
fn generate_path(si: &i32, graph: &Graph) -> Vec<i32> {
    let n = graph.len();
    let mut boundary = PFGraph::with_capacity(n);
    let mut finished = PFGraph::with_capacity(n);

    boundary.insert( si.clone(),
                     PFInfo {
                         avg: 0.,
                         cum: graph.get(&si).unwrap().borrow().gwlinks,
                         dist: 0,
                         prev: None } );

    // Keep grabbing the key corresponding the highest value until `boundary` is
    // empty
    while let Some( (currid, _) ) = boundary.iter().max_by_key(|x| x.1) {

        // Move the node from `boundary` to `finished`
        let val = boundary.remove(&currid).unwrap();
        finished.insert(currid.clone(), val);

        // Add or update all adjacent nodes that are not in `finished`
        for nbrid in graph.get(&currid).unwrap()
                          .borrow()
                          .nbrs.iter()
                          .filter(|x| !finished.contains_key(x)) {
            let currval = finished.get(&currid).unwrap();
            let prev = Some(currid.clone());
            let dist = currval.dist + 1;
            let cum = currval.cum + graph.get(nbrid).unwrap().borrow().gwlinks;
            let avg = cum as f32 / dist as f32;
            boundary.insert(
                nbrid.clone(),
                PFInfo {
                    avg: avg,
                    cum: cum,
                    dist: dist,
                    prev: prev,
                }
            );
        }
    }

    let mut path = Vec::new();
    let mut currid = finished.iter().max_by_key(|x| x.1).unwrap().0.clone();
    path.push(currid.clone());
    while let Some(previd) = finished.get(&currid).unwrap().prev {
        path.push(previd.clone());
        currid = previd.clone();
    }
    path.reverse();

    path
}



macro_rules! parse_input {
    ($x:expr, $t:ident) => ($x.trim().parse::<$t>().unwrap())
}

#[test]
fn test_generate_path() {
    let mut inputs = "8 13 2
6 2
7 3
6 3
5 3
3 4
7 1
2 0
0 1
0 3
1 3
2 3
7 4
6 5
4
5".lines();

    let header = inputs.next().unwrap().split_whitespace().collect::<Vec<_>>();
    let n = parse_input!(header[0], i32); // the total number of nodes in the level, including the gateways
    let l = parse_input!(header[1], i32); // the number of links
    let e = parse_input!(header[2], i32); // the number of exit gateways

    let mut graph = Graph::with_capacity(n as usize);
    for node in 0..n {
        graph.insert(node, RefCell::new(NodeInfo{ nbrs: HashSet::new(), gwlinks: 0 }));
    }
    let graph = graph;

    for _ in 0..l as usize {
        let link = inputs.next().unwrap();
        let nodes = link.split(" ").collect::<Vec<_>>();
        let n1 = parse_input!(nodes[0], i32); // N1 and N2 defines a link between these nodes
        let n2 = parse_input!(nodes[1], i32);

        graph.get(&n1).unwrap().borrow_mut().nbrs.insert(n2);
        graph.get(&n2).unwrap().borrow_mut().nbrs.insert(n1);
    }

    let mut gateways = HashSet::new();
    for _ in 0..e as usize {
        let ei = parse_input!(inputs.next().unwrap(), i32); // the index of a gateway node
        gateways.insert(ei);
    }
    let gateways = gateways;

    for gwid in &gateways {
        for gwnbr in &graph.get(gwid).unwrap().borrow().nbrs {
            (&graph).get(&gwnbr).unwrap().borrow_mut().gwlinks += 1;
        }
    }

    assert_eq!(generate_path(&0, &graph), vec![0, 3]);
}
while let Some( (currid, _) ) = boundary.iter().max_by_key(|x| x.1).clone() {
    //                                  ^---where borrow begins    ^---where borrow could end

    // Move the node from `boundary` to `finished`
    let val = boundary.remove(&currid).unwrap();
    finished.insert(currid.clone(), val);

    ...

} // <--- where borrow does end
while !boundary.is_empty() {
    let currid = boundary.iter().max_by_key(|x| x.1).unwrap().0.clone();
    //                   ^---where borrow begins               ^---where borrow ends
    // Move the node from `boundary` to `finished`
    let val = boundary.remove(&currid).unwrap();
    finished.insert(currid.clone(), val);

    ...

}