@@ -51,8 +51,26 @@ function _dominates(
5151 end
5252end
5353
54- function _sort! (solutions:: Vector{SolutionPoint} , sense:: MOI.OptimizationSense )
55- return sort! (solutions; by = x -> x. y, rev = sense == MOI. MAX_SENSE)
54+ # The use of `atol` when sorting is to work-around a tolerance issue that caused
55+ # a test failure in #181 that wasn't reproducible on macOS. It happened on linux
56+ # because of a minor version change in HiGHS.
57+ #
58+ # Consider two Y vectors `y1 = [22, 37, 63]` and `y2 = [22, 54, 47]`. We clearly
59+ # want to return them in the order `y1`, `y2`, but if `y1[1] = 22+eps` then
60+ # we'll get these "round the wrong way" from the user's perspective, even though
61+ # it would be numerically correct.
62+ #
63+ # My solution is just to round these to the nearest `atol`. The main situation
64+ # that this would be confusing is when the objective is integer and we sort
65+ # wrongly because of 0.9999999 and 1.00000001 etc.
66+ function _sort! (
67+ solutions:: Vector{SolutionPoint} ,
68+ sense:: MOI.OptimizationSense ;
69+ atol:: Float64 ,
70+ )
71+ digits = round (Int, log10 (atol))
72+ rev = sense == MOI. MAX_SENSE
73+ return sort! (solutions; by = p -> round .(p. y; digits), rev)
5674end
5775
5876"""
@@ -83,7 +101,7 @@ function filter_nondominated(
83101 push! (nondominated_solutions, candidate)
84102 end
85103 end
86- _sort! (nondominated_solutions, sense)
104+ _sort! (nondominated_solutions, sense; atol )
87105 return nondominated_solutions
88106end
89107
0 commit comments