Skip to content

Commit

Permalink
loads of debug statements added
Browse files Browse the repository at this point in the history
  • Loading branch information
joschout committed Oct 26, 2019
1 parent 39a7b54 commit b240ca0
Show file tree
Hide file tree
Showing 8 changed files with 157 additions and 18 deletions.
41 changes: 38 additions & 3 deletions submodmax/deterministic_double_greedy_search.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,15 +27,26 @@ def __init__(self, objective_function: AbstractSubmodularFunction, ground_set: S
super().__init__(objective_function, ground_set, debug)

def optimize(self) -> Set[E]:
if self.debug:
print("=========================================================")
print("START submodmax.DeterministicDoubleGreedySearch optimizer")
print("=========================================================")

X_prev: Set[E] = set()
Y_prev: Set[E] = self.ground_set.copy()

f_on_X_prev: float = self.objective_function.evaluate(X_prev)
f_on_Y_prev: float = self.objective_function.evaluate(Y_prev)

elem: E
for elem in self.ground_set:
ground_set_size: int = len(self.ground_set)

if self.debug:
print("initialization:")
print("X0 : size: ", len(X_prev), "/", ground_set_size, ", f(S): ", f_on_X_prev)
print("Y0: size: ", len(Y_prev), "/", ground_set_size, ", f(S): ", f_on_Y_prev)

elem: E
for i, elem in enumerate(self.ground_set, 1):
X_prev_plus_elem: Set[E] = X_prev | {elem}
f_on_X_prev_plus_elem: float = self.objective_function.evaluate(X_prev_plus_elem)
a: float = f_on_X_prev_plus_elem - f_on_X_prev
Expand All @@ -44,18 +55,42 @@ def optimize(self) -> Set[E]:
f_on_Y_prev_minus_elem: float = self.objective_function.evaluate(Y_prev_minus_elem)
b: float = f_on_Y_prev_minus_elem - f_on_Y_prev

if self.debug:
print()
print("element ", i, "/", ground_set_size)
print("\t X_prev --> size: ", len(X_prev), ", f(S):", f_on_Y_prev)
print("\t X" + str(i) + " + e" + str(i) + " --> size: ", len(X_prev_plus_elem), ", f(S):",
f_on_X_prev_plus_elem)
print()
print("\t Y_prev --> size: ", len(Y_prev), ", f(S):", f_on_Y_prev)
print("\t Y" + str(i) + " - e" + str(i) + " --> size: ", len(Y_prev_minus_elem), ", f(S):",
f_on_Y_prev_minus_elem)

print("\t\ta =", a)
print("\t\tb =", b)

if a >= b:
X_prev = X_prev_plus_elem
f_on_X_prev = f_on_X_prev_plus_elem
# Y_prev stays the same
if self.debug:
print("\ta >= b")
print("\tUPDATE X_prev:")
print("\tX_prev --> size:", len(X_prev), ", f(X_prev):", f_on_X_prev)
else:
# X_prev stays the same
Y_prev = Y_prev_minus_elem
f_on_Y_prev = f_on_Y_prev_minus_elem
if self.debug:
print("\ta < b")
print("\tUPDATE Y_prev:")
print("\tY_prev --> size:", len(Y_prev), ", f(Y_prev):", f_on_Y_prev)

if not X_prev == Y_prev:
raise Exception("both sets should be equal")

if self.debug:
print("-- finished iteration --")
print("X_prev --> size:", len(X_prev), ", f(X_prev):", f_on_X_prev)
print("Y_prev --> size:", len(Y_prev), ", f(Y_prev):", f_on_Y_prev)
print("obj val local optimum:", str(f_on_X_prev))
return X_prev
6 changes: 5 additions & 1 deletion submodmax/deterministic_local_search.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,9 +32,13 @@ def __init__(self, objective_function: AbstractSubmodularFunction, ground_set: S
super().__init__(objective_function, ground_set, debug)
self.epsilon: float = epsilon
n: int = len(ground_set)
self.rho: float = 0.5 * (1 + self.epsilon / (n * n))
self.rho: float = (1 + self.epsilon / (n * n))

def optimize(self) -> Set[E]:
if self.debug:
print("==================================================")
print("START submodmax.DeterministicLocalSearch optimizer")
print("==================================================")
solution_set, func_val1 = self._deterministic_local_search() # type: Set[E], float
complement_of_solution_set: Set[E] = self.ground_set - solution_set
func_val2: float = self.objective_function.evaluate(complement_of_solution_set)
Expand Down
24 changes: 20 additions & 4 deletions submodmax/deterministic_local_search_pyids.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,10 @@ def __init__(self, objective_function: AbstractSubmodularFunction, ground_set: S
self.rho: float = (1 + self.epsilon / (n * n))

def optimize(self) -> Set[E]:
if self.debug:
print("=======================================================")
print("START submodmax.DeterministicLocalSearchPyIDS optimizer")
print("=======================================================")
solution_set: Set[E] = self._deterministic_local_search()
complement_of_solution_set: Set[E] = self.ground_set - solution_set

Expand Down Expand Up @@ -79,14 +83,23 @@ def _deterministic_local_search(self) -> Set[E]:
restart_computations: bool = False

while True:
if self.debug:
print("Current solution set size:", len(solution_set))
print("Current solution set:")
for i, elem in enumerate(solution_set, 1):
print("\t", i, elem)


# -- Adding elements to S
# Keep adding elements to S so long as the improvement is larger than (1 + epsilon)/ n²
# i.e. f(S + e) - f(S) > (1 + epsilon)/ n²
if self.debug:
print("Start check of adding 1 elem")

elem: E
for elem in self.ground_set - solution_set:
if self.debug:
print("Testing if elem is good to add " + str(elem))
print("\tTesting if elem is good to add " + str(elem))

modified_solution_set: Set[E] = solution_set | {elem}
func_val: float = self.objective_function.evaluate(modified_solution_set)
Expand All @@ -102,6 +115,7 @@ def _deterministic_local_search(self) -> Set[E]:
print("Adding to the solution set elem: " + str(elem))
print("-----------------------")
break
print("No good addition found")

# ----------------

Expand All @@ -110,18 +124,19 @@ def _deterministic_local_search(self) -> Set[E]:
continue

# --- Discarding elements of S ---

if self.debug:
print("Start check of deleting 1 elem")
elem: E
for elem in solution_set:
if self.debug:
print("Testing should remove elem " + str(elem))
print("\tTesting should remove elem " + str(elem))

modified_solution_set: Set[E] = solution_set - {elem}
func_val: float = self.objective_function.evaluate(modified_solution_set)

if func_val > self.rho * soln_set_obj_func_value:
# add this element to solution set and recompute omegas
solution_set.add(elem)
solution_set.remove(elem)
soln_set_obj_func_value = func_val
restart_computations = True

Expand All @@ -131,6 +146,7 @@ def _deterministic_local_search(self) -> Set[E]:
print("-----------------------")
break
# ----------------
print("No good deletion found")

if restart_computations:
restart_computations = False
Expand Down
40 changes: 39 additions & 1 deletion submodmax/randomized_double_greedy_search.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,14 +34,26 @@ def __init__(self, objective_function: AbstractSubmodularFunction, ground_set: S
super().__init__(objective_function, ground_set, debug)

def optimize(self) -> Set[E]:
if self.debug:
print("======================================================")
print("START submodmax.RandomizedDoubleGreedySearch optimizer")
print("======================================================")

X_prev: Set[E] = set()
Y_prev: Set[E] = self.ground_set.copy()

f_on_X_prev: float = self.objective_function.evaluate(X_prev)
f_on_Y_prev: float = self.objective_function.evaluate(Y_prev)

ground_set_size: int = len(self.ground_set)

if self.debug:
print("initialization:")
print("X0 : size: ", len(X_prev), "/", ground_set_size, ", f(S): ", f_on_X_prev)
print("Y0: size: ", len(Y_prev), "/", ground_set_size, ", f(S): ", f_on_Y_prev)

elem: E
for elem in self.ground_set:
for i, elem in enumerate(self.ground_set, 1):
X_prev_plus_elem: Set[E] = X_prev | {elem}
f_on_X_prev_plus_elem: float = self.objective_function.evaluate(X_prev_plus_elem)
a: float = f_on_X_prev_plus_elem - f_on_X_prev
Expand All @@ -61,20 +73,46 @@ def optimize(self) -> Set[E]:

random_value: float = np.random.uniform()

if self.debug:
print()
print("element ", i, "/", ground_set_size)
print("\t X_prev --> size: ", len(X_prev), ", f(S):", f_on_Y_prev)
print("\t X" + str(i) + " + e" + str(i) + " --> size: ", len(X_prev_plus_elem), ", f(S):",
f_on_X_prev_plus_elem)

print("\t Y_prev --> size: ", len(Y_prev), ", f(S):", f_on_Y_prev)
print("\t Y" + str(i) + " - e" + str(i) + " --> size: ", len(Y_prev_minus_elem), ", f(S):", f_on_Y_prev_minus_elem)

print("\t\ta =", a, "-> a' = ", a_prime)
print("\t\tb =", b, "-> b' = ", b_prime)
print("\t\tprob_bound =", prob_boundary)
print("\t\trand_val = ", random_value)

if random_value <= prob_boundary:
X_prev = X_prev_plus_elem
f_on_X_prev = f_on_X_prev_plus_elem
# Y_prev stays the same
if self.debug:
print("\trandom_value <= prob_boundary")
print("\tUPDATE X_prev:")
print("\tX_prev --> size:", len(X_prev), ", f(X_prev):", f_on_X_prev)
else:
# X_prev stays the same
Y_prev = Y_prev_minus_elem
f_on_Y_prev = f_on_Y_prev_minus_elem
if self.debug:
print("\trandom_value > prob_boundary")
print("\tUPDATE Y_prev:")
print("\tY_prev --> size:", len(Y_prev), ", f(Y_prev):", f_on_Y_prev)

warnings.warn("remove equality check")

if not X_prev == Y_prev:
raise Exception("both sets should be equal")

if self.debug:
print("-- finished iteration --")
print("X_prev --> size:", len(X_prev), ", f(X_prev):", f_on_X_prev)
print("Y_prev --> size:", len(Y_prev), ", f(Y_prev):", f_on_Y_prev)
print("obj val local optimum:", str(f_on_X_prev))
return X_prev
5 changes: 3 additions & 2 deletions submodmax/value_reuse/abstract_optimizer.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
from typing import Set, TypeVar, Optional, Tuple

from value_reuse.set_info import SetInfo
from .set_info import SetInfo

E = TypeVar('E')

Expand All @@ -21,7 +21,8 @@ def evaluate(self, current_set_info: SetInfo,

class AbstractOptimizerValueReuse:

def __init__(self, objective_function: AbstractSubmodularFunctionValueReuse, ground_set: Set[E], debug: bool = True):
def __init__(self, objective_function: AbstractSubmodularFunctionValueReuse, ground_set: Set[E],
debug: bool = True):
self.objective_function: AbstractSubmodularFunctionValueReuse = objective_function
self.ground_set: Set[E] = ground_set
self.debug: bool = debug
Expand Down
4 changes: 4 additions & 0 deletions submodmax/value_reuse/deterministic_double_greedy_search.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,10 @@ def __init__(self, objective_function: AbstractSubmodularFunctionValueReuse, gro
super().__init__(objective_function, ground_set, debug)

def optimize(self) -> Tuple[SetInfo, FuncInfo]:
if self.debug:
print("=====================================================================")
print("START submodmax.value_reuse.DeterministicDoubleGreedySearch optimizer")
print("=====================================================================")
# X_prev: Set[E] = set()
# Y_prev: Set[E] = self.ground_set.copy(

Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
from typing import Set, Tuple, Optional, TypeVar

from value_reuse.abstract_optimizer import AbstractSubmodularFunctionValueReuse, AbstractOptimizerValueReuse, FuncInfo
from value_reuse.set_info import SetInfo
from .abstract_optimizer import AbstractSubmodularFunctionValueReuse, AbstractOptimizerValueReuse, FuncInfo
from .set_info import SetInfo

E = TypeVar('E')

Expand Down Expand Up @@ -38,6 +38,11 @@ def __init__(self, objective_function: AbstractSubmodularFunctionValueReuse, gro
self.empty_set = set()

def optimize(self) -> Tuple[SetInfo, FuncInfo]:
if self.debug:
print("==================================================")
print("START DeterministicLocalSearchValueReuse optimizer")
print("==================================================")

solution_set_info: SetInfo
func_info1: FuncInfo

Expand All @@ -56,11 +61,21 @@ def optimize(self) -> Tuple[SetInfo, FuncInfo]:

if func_info1.func_value >= func_info2.func_value:
if self.debug:
print("Objective value of solution set:", func_info1.func_value)
print("Choosing first set as solution.")
print("Objective value of chosen solution set:", func_info1.func_value)
print("Chosen solution set size:", solution_set_info.current_set_size, " / ", len(self.ground_set))
print("Objective value of other set:", func_info2.func_value)
print("Other set size:", complement_set_info.current_set_size, " / ", len(self.ground_set))

return solution_set_info, func_info1
else:
if self.debug:
print("Objective value of solution set:", func_info2.func_value)
print("Choosing second set as solution.")
print("Objective value of chosen solution set:", func_info2.func_value)
print("Chosen solution set size:", complement_set_info.current_set_size, " / ", len(self.ground_set))
print("Objective value of other set:", func_info1.func_value)
print("Other set size:", solution_set_info.current_set_size, " / ", len(self.ground_set))

return complement_set_info, func_info2

def _get_initial_subset_and_objective_function_value(self) -> Tuple[SetInfo, FuncInfo]:
Expand Down Expand Up @@ -115,8 +130,12 @@ def _deterministic_local_search(self) -> Tuple[SetInfo, FuncInfo]:
local_optimum_found: bool = False
while not local_optimum_found:
# keep adding elements until there is no improvement

size_before_adding = solution_set_info.current_set_size
solution_set_info, solution_set_func_info = self._add_elements_until_no_improvement(
solution_set_info, solution_set_func_info)
size_after_adding = solution_set_info.current_set_size
print("Added", size_after_adding - size_before_adding, "elements", "(Current size:", size_after_adding, ")", "WITH val reuse")

# check if removing an element leads to improvement
# if it does, restart with adding elements
Expand All @@ -127,6 +146,8 @@ def _deterministic_local_search(self) -> Tuple[SetInfo, FuncInfo]:
local_optimum_found = True
else:
solution_set_info, solution_set_func_info = an_improved_subset
size_after_deleting = solution_set_info.current_set_size
print("Deleted ", size_after_adding - size_after_deleting, "elements", "(Current size:", size_after_deleting, ")", "WITH val reuse")

return solution_set_info, solution_set_func_info

Expand All @@ -142,6 +163,10 @@ def _add_elements_until_no_improvement(self,

improvement_possible_by_adding: bool = True
while improvement_possible_by_adding:

if current_set_info.current_set is None:
raise Exception("Warning: this should never happen!")

an_improved_subset: Optional[Tuple[SetInfo, FuncInfo]] = self._find_improved_subset_by_adding_one_element(
solution_set_info, solution_set_func_info)
if an_improved_subset is not None:
Expand Down Expand Up @@ -179,12 +204,17 @@ def _find_improved_subset_by_adding_one_element(self,
continue

if self.debug:
print("Testing if elem is good to add " + str(elem))
print("\tTesting if elem is good to add " + str(elem))
added_elem: Set[E] = {elem}

mod_solution_set_info.added_elems = added_elem
func_info_mod_solution_set: FuncInfo = self.objective_function.evaluate(mod_solution_set_info,
solution_set_func_info)
diff = func_info_mod_solution_set.func_value - self.rho * solution_set_func_info.func_value

# print("\tfunc val mod set:", func_info_mod_solution_set.func_value)
# print("\tfunc val unmod :", solution_set_func_info.func_value)
# print("\tdiff:", diff)

if func_info_mod_solution_set.func_value > self.rho * solution_set_func_info.func_value:
if self.debug:
Expand All @@ -195,9 +225,15 @@ def _find_improved_subset_by_adding_one_element(self,
# mod_solution_set_info.current_set = mod_solution_set
mod_solution_set_info.current_set = mod_solution_set

if mod_solution_set_info.current_set is None:
raise Exception("uninitialized current set")

return mod_solution_set_info, func_info_mod_solution_set
# return mod_solution_set_info, func_info_mod_solution_set
# None of the remaining elements increase the objective function with more than (1 + epsilon / (n * n))
# if mod_solution_set_info.current_set is None:
# raise Exception("uninitialized current set")

return None

def _find_improved_subset_by_discarding_one_element(self,
Expand All @@ -216,7 +252,7 @@ def _find_improved_subset_by_discarding_one_element(self,

for elem in solution_set_info.current_set:
if self.debug:
print("Testing should remove elem " + str(elem))
print("\tTesting should remove elem " + str(elem))

deleted_elem = {elem}

Expand All @@ -232,7 +268,7 @@ def _find_improved_subset_by_discarding_one_element(self,
print("-----------------------")
print("Removing from solution set elem " + str(elem))
print("-----------------------")

mod_solution_set_info.current_set = mod_solution_set
return mod_solution_set_info, func_info_mod_solution_set
else:
mod_solution_set.add(elem)
Expand Down
Loading

0 comments on commit b240ca0

Please sign in to comment.