Skip to content

Commit

Permalink
Add the OPAMSOLVERTOLERANCE environment variable to allow users to fi…
Browse files Browse the repository at this point in the history
…x solver timeouts for good
  • Loading branch information
kit-ty-kate committed Apr 14, 2023
1 parent 0a174e1 commit 348ffe5
Show file tree
Hide file tree
Showing 13 changed files with 42 additions and 11 deletions.
1 change: 1 addition & 0 deletions doc/pages/Tricks.md
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,7 @@ The following sequence of commands tries to install as much packages as possible
opam update
opam switch create . ocaml-base-compiler.$(VERSION)
export OPAMSOLVERTIMEOUT=3600
export OPAMSOLVERTOLERANCE=1.0
opam list --available -s | xargs opam install --best-effort --yes
# Be patient
```
10 changes: 10 additions & 0 deletions src/client/opamArg.ml
Original file line number Diff line number Diff line change
Expand Up @@ -186,6 +186,16 @@ let environment_variables =
"change the time allowance of the solver. Default is %.1f, set to 0 \
for unlimited. Note that all solvers may not support this option."
(OpamStd.Option.default 0. OpamSolverConfig.(default.solver_timeout)));
"SOLVERTOLERANCE", cli_from cli2_2, (fun v -> SOLVERTOLERANCE (env_float v)),
(Printf.sprintf
"changes the tolerance towards the solver choosing an unoptimized \
solution (i.e. might pull outdated packages). Typical values range \
from 0.0 (best solution known to the solver) to 1.0 (unoptimized \
solution). Default is %.1f. This option is useful in case the solver \
can't find a solution in a reasonable time \
(see $(b,\\$OPAMSOLVERTIMEOUT)). Note that all solvers may not \
support this option."
(OpamStd.Option.default 0. OpamSolverConfig.default.solver_tolerance));
"UPGRADECRITERIA", cli_original,
(fun v -> UPGRADECRITERIA (env_string v)),
"specifies user $(i,preferences) for dependency solving when performing \
Expand Down
1 change: 1 addition & 0 deletions src/client/opamClientConfig.mli
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,7 @@ val opam_init:
?solver_preferences_fixup:string option Lazy.t ->
?solver_preferences_best_effort_prefix: string option Lazy.t ->
?solver_timeout:float option ->
?solver_tolerance:float option ->
?solver_allow_suboptimal:bool ->
?cudf_trim:string option ->
?dig_depth:int ->
Expand Down
2 changes: 1 addition & 1 deletion src/solver/opamBuiltin0install.ml
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ let parse_criteria criteria =
OpamConsole.warning "Criteria '%s' is not supported by the 0install solver" criteria;
default

let call ~criteria ?timeout:_ (preamble, universe, request) =
let call ~criteria ?timeout:_ ?tolerance:_ (preamble, universe, request) =
let {drop_installed_packages; prefer_oldest} = parse_criteria criteria in
let timer = OpamConsole.timer () in
let pkgs, constraints = create_spec ~drop_installed_packages universe request in
Expand Down
2 changes: 1 addition & 1 deletion src/solver/opamBuiltinMccs.dummy.ml
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ module S = struct
crit_best_effort_prefix = None;
}

let call ~criteria:_ ?timeout:_ _cudf =
let call ~criteria:_ ?timeout:_ ?tolerance:_ _cudf =
failwith "This opam was compiled without a solver built in"
end

Expand Down
5 changes: 3 additions & 2 deletions src/solver/opamBuiltinMccs.real.ml
Original file line number Diff line number Diff line change
Expand Up @@ -31,15 +31,16 @@ let default_criteria = {
crit_best_effort_prefix = Some "+count[opam-query:,false],";
}

let call solver_backend ext ~criteria ?timeout cudf =
let call solver_backend ext ~criteria ?timeout ?tolerance cudf =
let solver = match solver_backend, ext with
| `LP _, Some ext -> `LP ext
| _ -> solver_backend
in
match
Mccs.resolve_cudf
~solver
~verbose:OpamCoreConfig.(abs !r.debug_level >= 2)
?mip_gap:tolerance
~verbosity:(!OpamCoreConfig.r.debug_level - 1) (* *)
?timeout criteria cudf
with
| None -> raise Dose_common.CudfSolver.Unsat
Expand Down
2 changes: 1 addition & 1 deletion src/solver/opamBuiltinZ3.dummy.ml
Original file line number Diff line number Diff line change
Expand Up @@ -27,5 +27,5 @@ let default_criteria = {
crit_best_effort_prefix = None;
}

let call ~criteria:_ ?timeout:_ _cudf =
let call ~criteria:_ ?timeout:_ ?tolerance:_ _cudf =
failwith "This opam was compiled without the Z3 solver built in"
3 changes: 2 additions & 1 deletion src/solver/opamBuiltinZ3.real.ml
Original file line number Diff line number Diff line change
Expand Up @@ -465,13 +465,14 @@ let extract_solution_packages universe opt =
[]
| None -> failwith "no model ??"

let call ~criteria ?timeout (preamble, universe, _ as cudf) =
let call ~criteria ?timeout ?tolerance:_ (preamble, universe, _ as cudf) =
(* try *)
log "Generating problem...";
let cfg = match timeout with
| None -> []
| Some secs -> ["timeout", string_of_int (int_of_float (1000. *. secs))]
in
(* TODO: use tolerance. Maybe the rlimit cfg option + intermediate solution could be used *)
let ctx = {
z3 = Z3.mk_context cfg;
pkgs = Hashtbl.create 2731;
Expand Down
7 changes: 5 additions & 2 deletions src/solver/opamCudf.ml
Original file line number Diff line number Diff line change
Expand Up @@ -1498,9 +1498,12 @@ let call_external_solver ~version_map univ req =
let msg =
Printf.sprintf
"Sorry, resolution of the request timed out.\n\
Try to specify a more precise request, use a different solver, or \
increase the allowed time by setting OPAMSOLVERTIMEOUT to a bigger \
Try to specify a more precise request, use a different solver, \
increase the tolerance for unoptimized solutions by setting \
OPAMSOLVERTOLERANCE to a bigger value (currently, it is set to %.1f) \
or increase the allowed time by setting OPAMSOLVERTIMEOUT to a bigger \
value (currently, it is set to %.1f seconds)."
OpamSolverConfig.(OpamStd.Option.default 0. !r.solver_tolerance)
OpamSolverConfig.(OpamStd.Option.default 0. !r.solver_timeout)
in
raise (Solver_failure msg)
Expand Down
2 changes: 1 addition & 1 deletion src/solver/opamCudfSolver.ml
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ module type ExternalArg = sig
val default_criteria: criteria_def
end

let call_external_solver command ~criteria ?timeout (_, universe,_ as cudf) =
let call_external_solver command ~criteria ?timeout ?tolerance:_ (_, universe,_ as cudf) =
let solver_in =
OpamFilename.of_string (OpamSystem.temp_file "solver-in") in
let solver_out =
Expand Down
2 changes: 1 addition & 1 deletion src/solver/opamCudfSolverSig.ml
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ module type S = sig
it's only run if the solver returns unsat, to extract the explanations. *)

val call:
criteria:string -> ?timeout:float -> Cudf.cudf ->
criteria:string -> ?timeout:float -> ?tolerance:float -> Cudf.cudf ->
Cudf.preamble option * Cudf.universe

end
13 changes: 12 additions & 1 deletion src/solver/opamSolverConfig.ml
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ module E = struct
| PREPRO of bool option
| SOLVERALLOWSUBOPTIMAL of bool option
| SOLVERTIMEOUT of float option
| SOLVERTOLERANCE of float option
| UPGRADECRITERIA of string option
| USEINTERNALSOLVER of bool option
| VERSIONLAGPOWER of int option
Expand All @@ -42,6 +43,7 @@ module E = struct
let solverallowsuboptimal =
value (function SOLVERALLOWSUBOPTIMAL b -> b | _ -> None)
let solvertimeout = value (function SOLVERTIMEOUT f -> f | _ -> None)
let solvertolerance = value (function SOLVERTOLERANCE f -> f | _ -> None)
let useinternalsolver = value (function USEINTERNALSOLVER b -> b | _ -> None)
let upgradecriteria = value (function UPGRADECRITERIA s -> s | _ -> None)
let versionlagpower = value (function VERSIONLAGPOWER i -> i | _ -> None)
Expand All @@ -59,6 +61,7 @@ type t = {
solver_preferences_fixup: string option Lazy.t;
solver_preferences_best_effort_prefix: string option Lazy.t;
solver_timeout: float option;
solver_tolerance: float option;
solver_allow_suboptimal: bool;
cudf_trim: string option;
dig_depth: int;
Expand All @@ -75,6 +78,7 @@ type 'a options_fun =
?solver_preferences_fixup:string option Lazy.t ->
?solver_preferences_best_effort_prefix:string option Lazy.t ->
?solver_timeout:float option ->
?solver_tolerance:float option ->
?solver_allow_suboptimal:bool ->
?cudf_trim:string option ->
?dig_depth:int ->
Expand All @@ -95,6 +99,7 @@ let default =
solver_preferences_fixup = lazy None;
solver_preferences_best_effort_prefix = lazy None;
solver_timeout = Some 60.;
solver_tolerance = Some 0.0;
solver_allow_suboptimal = true;
cudf_trim = None;
dig_depth = 2;
Expand All @@ -111,6 +116,7 @@ let setk k t
?solver_preferences_fixup
?solver_preferences_best_effort_prefix
?solver_timeout
?solver_tolerance
?solver_allow_suboptimal
?cudf_trim
?dig_depth
Expand All @@ -133,6 +139,8 @@ let setk k t
solver_preferences_best_effort_prefix;
solver_timeout =
t.solver_timeout + solver_timeout;
solver_tolerance =
t.solver_tolerance + solver_tolerance;
solver_allow_suboptimal =
t.solver_allow_suboptimal + solver_allow_suboptimal;
cudf_trim = t.cudf_trim + cudf_trim;
Expand Down Expand Up @@ -193,6 +201,8 @@ let initk k =
E.besteffortprefixcriteria () >>| fun c -> (lazy (Some c)) in
let solver_timeout =
E.solvertimeout () >>| fun f -> if f <= 0. then None else Some f in
let solver_tolerance =
E.solvertolerance () >>| fun f -> if f <= 0. then None else Some f in
setk (setk (fun c -> r := with_auto_criteria c; k)) !r
~cudf_file:(E.cudffile ())
~solver
Expand All @@ -202,6 +212,7 @@ let initk k =
?solver_preferences_fixup:fixup_criteria
?solver_preferences_best_effort_prefix:best_effort_prefix_criteria
?solver_timeout
?solver_tolerance
?solver_allow_suboptimal:(E.solverallowsuboptimal ())
~cudf_trim:(E.cudftrim ())
?dig_depth:(E.digdepth ())
Expand Down Expand Up @@ -253,6 +264,6 @@ let call_solver ~criteria cudf =
OpamConsole.log "SOLVER" "Calling solver %s with criteria %s"
(OpamCudfSolver.get_name (module S)) criteria;
let chrono = OpamConsole.timer () in
let r = S.call ~criteria ?timeout:(!r.solver_timeout) cudf in
let r = S.call ~criteria ?timeout:(!r.solver_timeout) ?tolerance:(!r.solver_tolerance) cudf in
OpamConsole.log "SOLVER" "External solver took %.3fs" (chrono ());
r
3 changes: 3 additions & 0 deletions src/solver/opamSolverConfig.mli
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ module E : sig
| PREPRO of bool option
| SOLVERALLOWSUBOPTIMAL of bool option
| SOLVERTIMEOUT of float option
| SOLVERTOLERANCE of float option
| UPGRADECRITERIA of string option
| USEINTERNALSOLVER of bool option
| VERSIONLAGPOWER of int option
Expand All @@ -40,6 +41,7 @@ type t = private {
solver_preferences_fixup: string option Lazy.t;
solver_preferences_best_effort_prefix: string option Lazy.t;
solver_timeout: float option;
solver_tolerance: float option;
solver_allow_suboptimal: bool;
cudf_trim: string option;
dig_depth: int;
Expand All @@ -56,6 +58,7 @@ type 'a options_fun =
?solver_preferences_fixup:string option Lazy.t ->
?solver_preferences_best_effort_prefix:string option Lazy.t ->
?solver_timeout:float option ->
?solver_tolerance:float option ->
?solver_allow_suboptimal:bool ->
?cudf_trim:string option ->
?dig_depth:int ->
Expand Down

0 comments on commit 348ffe5

Please sign in to comment.