diff --git a/sho/iters.py b/sho/iters.py index de3c4fa..6762750 100644 --- a/sho/iters.py +++ b/sho/iters.py @@ -1,16 +1,50 @@ import sys +from collections import deque ######################################################################## # Stopping criterions ######################################################################## def max(i, val, sol, nb_it): + """Stop after reaching nb_it iterations.""" if i < nb_it: return True else: return False +def target(i, val, sol, target): + """Stop after reaching target value.""" + if val < target: + return True + else: + return False + + +class steady: + """Stop if improvement is lesser than epsilon, in the last delta iterations.""" + + def __init__(self, delta, epsilon = 0): + self.epsilon = epsilon + self.delta = delta + self.delta_vals = deque() + + def __call__(self, i, val, sol): + if i < self.delta: # Always wait the first delta iterations. + self.delta_vals.append(val) + return True + + else: + #FILO stack. + self.delta_vals.popleft() + self.delta_vals.append(val) + + if val - self.delta_vals[0] <= self.epsilon: + return False # Stop here. + else: + return True + + # Stopping criterions that are actually just checkpoints. def several(i, val, sol, agains): diff --git a/snp.py b/snp.py index 2847bea..ef55f00 100644 --- a/snp.py +++ b/snp.py @@ -34,9 +34,14 @@ if __name__=="__main__": can.add_argument("-m", "--solver", metavar="NAME", choices=solvers, default="num_greedy", help="Solver to use, among: "+", ".join(solvers)) - # TODO add the corresponding stopping criterion. - can.add_argument("-t", "--target", metavar="VAL", default=1e-3, type=float, - help="Function value target delta") + can.add_argument("-t", "--target", metavar="VAL", default=30*30, type=float, + help="Objective function value target") + + can.add_argument("-y", "--steady-delta", metavar="NB", default=50, type=float, + help="Stop if no improvement after NB iterations") + can.add_argument("-e", "--steady-epsilon", metavar="DVAL", default=0, type=float, + help="Stop if the improvement of the objective function value is lesser than DVAL") + the = can.parse_args() @@ -67,7 +72,10 @@ if __name__=="__main__": make.iter(iters.log, fmt="\r{it} {val}"), make.iter(iters.history, - history = history) + history = history), + make.iter(iters.target, + target = the.target), + iters.steady(the.steady_delta, the.steady_epsilon) ] )