def find_min(constraints, expr, default_min=0): if type(expr) == int: return expr constraint_strs = [f'{c}' for c in constraints] min_optimize = Optimize() min_optimize.set('timeout', 10000) min_optimize.assert_exprs(*constraints) min_optimize.minimize(expr) status = min_optimize.check() if status != sat: print(f'Unable to find min ({status}) for:\n' + '\n'.join(constraint_strs)) return None min_val = min_optimize.model().eval(expr).as_long() # Make sure it's actually the min, since z3 has a bug # https://github.com/Z3Prover/z3/issues/4670 solver = Solver() solver.set('timeout', 10000) solver.add(constraints + [expr < min_val]) status = solver.check() if status != unsat: print( f'Z3 bug\nFind min ({expr}) => {min_val} with status ({status}):\n' + '\n'.join(constraint_strs)) return None return min_val
def find_max(constraints, expr, l = None): if l is None: l = logger if type(expr) == int: return expr constraint_strs = [f'{c}' for c in constraints] max_optimize = Optimize() max_optimize.set('timeout', 10000) max_optimize.assert_exprs(*constraints) max_optimize.maximize(expr) status = max_optimize.check() if status != sat: l.warning(f'Unable to find max ({status}) for:\n' + '\n'.join(constraint_strs)) return None max_val = max_optimize.model().eval(expr).as_long() # Make sure it's actually the max, since z3 has a bug # https://github.com/Z3Prover/z3/issues/4670 solver = Solver() solver.set('timeout', 10000) solver.add(constraints + [expr > max_val]) status = solver.check() if status != unsat: l.error(f'Z3 bug\nFind max ({expr}) => {max_val} with status ({status}):\n' + '\n'.join(constraint_strs)) return None return max_val