Compare mutable option and then assign a new value

I have code like this, but I can't figure out what the borrow checker wants me to do.

let mut optimum = None;
for parameter in problem_space.iter() {
        let mut solution = Vec::with_capacity(solution_len);
        let found = solve(&mut solution, parameter);
        if !found { // further iteration won't improve the result
            break;
        } else if optimum == None || solution.len() < optimum.unwrap().len() {
            optimum = Some(solution);
        }
    }

solution is moved in the else if branch, but I need to assign it to the optimum. Can I do this without cloning? Or maybe can I restructure my code?

I'm passing solution as a mutable reference because the solve function calls itself recursively and I want to reuse the buffer.

Your example is incomplete and you didn't include the error, so it's hard to tell. If the error was about optimum, here's one possibility:

else if optimum.as_ref().map(|o| o.len()).unwrap_or(0) > solution.len()

You're creating a new vector each loop; did you mean to reuse it across loops as much as possible?

1 Like

Your code works, but I instead of unwrap_or(0) I'd need to put something like unwrap_or(infinity). I just put a very high value to see if it works, and it does. Is there a more elegant way (I guess I could use std::usize::MAX)?

My specific code looks different, I abstracted it to be more useful to future readers. Maybe that was a bad idea.

This is my actual code:

pub fn vertex_cover_exact(&self, min_depth: usize, max_depth: usize) -> Option<Vec<u32>> {
        let mut min_cover: Option<Vec<u32>> = None;
        for depth in (min_depth..=max_depth).rev() {
            let mut cover = Vec::with_capacity(self.num_nodes());
            let mut uncovered = self.edges();
            let found = self.vertex_cover_exact_worker(&mut cover, &mut uncovered, depth);
            if !found {
                break;
            } else if cover.len() < min_cover.as_ref().map(|x| x.len()).unwrap_or(999999999) {
                min_cover = Some(cover);
            }
        }
        min_cover
    }

You're creating a new vector each loop; did you mean to reuse it across loops as much as possible?

The buffer cover has to be reused in the function self.vertex_cover_exact_worker(...) (which recurses). It wouldn't be too bad to recreate it each time in the loop itself though, I just need a clean state. Maybe it would be better to move it out of the loop as well and call cover.clear().

This also works:

1 Like

You would also have to clone it sometimes to keep a copy in optimum. If it's not causing a performance problem currently, I'd leave it as-is.

1 Like

I like this solution, it's more general and a bit more explicit. I'll use that. Didn't know about the ref keyword. I tried & instead of ref and that doesn't work. Also didn't know you could do an additional check like this in a match arm like you do in the second match arm in your example. I guess I still have a lot of reading to do.

Yeah, I just noticed that. The majority of work is in the worker function anyway, so I don't think it will give me any noticeable performance gain.