rust-lp-modeler icon indicating copy to clipboard operation
rust-lp-modeler copied to clipboard

Consider transforming Status to Result

Open jcavat opened this issue 6 years ago • 4 comments
trafficstars

And putting a solution only for Optimal and Suboptimal.

This would avoid testing the context in many situation.

jcavat avatar Oct 23 '19 15:10 jcavat

Optimal/Suboptimal for something ok and grouping Infeasible/Unbounded and Notsolved into one case containing error message details.

jcavat avatar Oct 23 '19 16:10 jcavat

Does this mean you're planning to treat Infeasible, Unbounded and/or Notsolved the same way as failing to read/write files or executing the solver? Or did you mean using Either instead of Result (which could be one interpretation of your 2nd comment) like:

Result<Either<WithSolution, WithoutSolution>, String>

I wouldn't aggregate status at this point already as this restricts the freedom of the consumer of this crate. Especially if the error cases are converted to String then, proper error handling will be messy and fragile (due to the need to match on these strings).

zappolowski avatar Oct 23 '19 18:10 zappolowski

I would prefer one of these solution :

Result<Solution, Error>
  • with NoSolution defining the Error trait and replace current String by Error and
  • Solution having a bool: is_optimal inside

Create our own Result with somethink like (or a variant of) :

enum Result {
  Optimal(Solution),
  SubOptimal(Solution),
  SolutionError(String),
  Error(Error)
}

I would prefer solution 1 for my part

jcavat avatar Oct 28 '19 11:10 jcavat

The first proposal would mix errors originating from actually trying to run the optimization (e.g. missing optimizer executable, unable to write either input or output files) with the infeasibility to find an optimal solution, which might in some cases be a valid outcome as well (e.g. for distribution problems Infeasible would indicate that the number of agents needs to be increased).

For the second proposal I see problems in error handling. I'm not sure, if it's easy to use ? in that case.

My proposal would be something like:

Result<Outcome, SomeErrorType or String>

with

enum Outcome {
    Optimal(Solution),
    SubOptimal(Solution),
    Infeasible,
    Unbounded,
}

(Outcome is the best I can come up with right now ... I'm bad at naming).

That way, one could use the standard error handling mechanisms and still has more fine grained control on how to interpret the actual optimization result. Usage in that case would roughly look like

let solution = match solver.run(&problem)? {
    Optimal(solution) | SubOptimal(solution) => solution,
    _ => return Err("boo"),
}

zappolowski avatar Oct 30 '19 14:10 zappolowski