let discriminant ?(bottom=false) ?(highest=true) evalsel vl constraints =
  let eval_constr = Hashtbl.create 17 in
  let constr_eval = Hashtbl.create 17 in
  let candidates = range ~bottom vl in
  List.iter (fun target ->
    let eval = List.map (evalsel target) constraints in
    try
      let v_rep = Hashtbl.find eval_constr eval in
      let l = Hashtbl.find constr_eval v_rep in
      Hashtbl.replace constr_eval v_rep (target::l)
    with Not_found -> begin
      Hashtbl.add eval_constr eval target;
      Hashtbl.add constr_eval target []
    end
  ) (if highest then List.rev candidates else candidates) ;
  (Hashtbl.fold (fun k v acc -> (k,v)::acc) constr_eval [])