def METHOD_NAME(self, depth: int = 5, epsilon: float = 1e-3):
    objective, constr_map = self.canonicalize()
    dims = self._format_for_solver(constr_map, s.ECOS)
    variables = self.objective.variables()
    for constr in self.constraints:
        variables += constr.variables()
    booleans = [v for v in variables if isinstance(v, Boolean)]
    self.constraints.extend(b._LB <= b for b in booleans)
    self.constraints.extend(b <= b._UB for b in booleans)
    result = bound(self, booleans)
    # check if gap is small enough
    if result['gap'] < epsilon:
        return result['obj']
    result = solve_wrapper(self, 0, booleans, depth, epsilon)
    # set the boolean values to the solution
    for b, value in zip(booleans, result['sol']):
        b.save_value(value)
        b.fix_values = cvxopt.matrix(True, b.size)
    return result['obj']