final presentation, restructure of the repository, updated code to have weighted probabilities and more
This commit is contained in:
298
code/main.py
298
code/main.py
@@ -30,18 +30,6 @@ def Continue(title="") -> None:
|
||||
print()
|
||||
|
||||
|
||||
# def MainMenu() -> None:
|
||||
# global currentFunction
|
||||
# options = ["Simulator", "Calculator", "Quit"]
|
||||
# actions: list[Callable[[], None]] = [SimulatorMenu, StopApplication]
|
||||
|
||||
# selectedIndex = ShowMenu(
|
||||
# options, title="Boolean Network Simulator\nby Tom Zuidberg"
|
||||
# )
|
||||
|
||||
# currentFunction = actions[selectedIndex]
|
||||
|
||||
|
||||
def StopApplication() -> None:
|
||||
quit()
|
||||
|
||||
@@ -151,11 +139,14 @@ def BooleanNetworkMenu(
|
||||
functionStrings: list = [None for _ in range(3)]
|
||||
functionsDirtyFlag = False
|
||||
current_highlight = 0
|
||||
functions_highlight = 0
|
||||
probFunctionStrings: list[list[str]] = [[] for _ in range(3)]
|
||||
|
||||
if bn is not None and funcStrings is not None and funcs is not None:
|
||||
boolNetwork = bn
|
||||
functions = funcs
|
||||
functionStrings = funcStrings
|
||||
probFunctionStrings = [[] for _ in range(boolNetwork.size)]
|
||||
|
||||
def Menu() -> None:
|
||||
nonlocal current_highlight
|
||||
@@ -164,10 +155,7 @@ def BooleanNetworkMenu(
|
||||
f"Set size (current: {boolNetwork.size}) WARNING: this will reset all other options!",
|
||||
f"Set state (current: {str(boolNetwork)[-boolNetwork.size :]})",
|
||||
f"Set update scheme (current: {boolNetwork.updateScheme})",
|
||||
*[
|
||||
f"Set update function of node x{i} (current: {functionStrings[i - 1]})"
|
||||
for i in range(1, boolNetwork.size + 1)
|
||||
],
|
||||
"Edit update functions",
|
||||
None,
|
||||
"Update once (hold ENTER for continuous updates)",
|
||||
"Update multiple times",
|
||||
@@ -182,7 +170,7 @@ def BooleanNetworkMenu(
|
||||
SetSizeHelper,
|
||||
SetStateHelper,
|
||||
SetUpdateSchemeHelper,
|
||||
*[partial(SetFunctionHelper, i) for i in range(boolNetwork.size)],
|
||||
FunctionsMenu,
|
||||
None,
|
||||
UpdateHelper,
|
||||
MultiUpdateHelper,
|
||||
@@ -204,7 +192,7 @@ def BooleanNetworkMenu(
|
||||
actions[selectedIndex]()
|
||||
|
||||
def SetSizeHelper() -> None:
|
||||
nonlocal boolNetwork, functions, functionStrings
|
||||
nonlocal boolNetwork, functions, functionStrings, probFunctionStrings
|
||||
while True:
|
||||
size = input("Set new size (Leave empty to cancel):\n").strip()
|
||||
if size == "":
|
||||
@@ -219,6 +207,7 @@ def BooleanNetworkMenu(
|
||||
boolNetwork = BooleanNetwork(size)
|
||||
functions = [None for _ in range(size)]
|
||||
functionStrings = [None for _ in range(size)]
|
||||
probFunctionStrings = [[] for _ in range(size)]
|
||||
return
|
||||
|
||||
def SetStateHelper() -> None:
|
||||
@@ -237,9 +226,32 @@ def BooleanNetworkMenu(
|
||||
print("Invalid input:", e)
|
||||
|
||||
def SetUpdateSchemeHelper() -> None:
|
||||
nonlocal boolNetwork
|
||||
nonlocal boolNetwork, functions, functionStrings, functionsDirtyFlag
|
||||
|
||||
def AdoptFromProbabilistic() -> None:
|
||||
nonlocal functionsDirtyFlag
|
||||
|
||||
for i in range(boolNetwork.size):
|
||||
if probFunctionStrings[i]:
|
||||
funcString = probFunctionStrings[i][0]
|
||||
func = eval(
|
||||
"lambda "
|
||||
+ ",".join(f"x{j}" for j in range(1, boolNetwork.size + 1))
|
||||
+ ":"
|
||||
+ funcString
|
||||
)
|
||||
functions[i] = func
|
||||
functionStrings[i] = funcString
|
||||
functionsDirtyFlag = True
|
||||
|
||||
def SwitchToSynchronous() -> None:
|
||||
wasProbabilistic = boolNetwork.updateScheme == "probabilistic"
|
||||
boolNetwork.UseSynchronousScheme()
|
||||
if wasProbabilistic:
|
||||
AdoptFromProbabilistic()
|
||||
|
||||
def SetSequentialHelper() -> None:
|
||||
wasProbabilistic = boolNetwork.updateScheme == "probabilistic"
|
||||
while True:
|
||||
seq = input(
|
||||
"Set sequence. (Leave empty to cancel)\nFormat example: '1,4,3,2'\n"
|
||||
@@ -252,26 +264,24 @@ def BooleanNetworkMenu(
|
||||
try:
|
||||
seq = [int(i) for i in seq]
|
||||
boolNetwork.UseSequentialScheme(seq)
|
||||
if wasProbabilistic:
|
||||
AdoptFromProbabilistic()
|
||||
return
|
||||
except Exception as e:
|
||||
print("Invalid input:", e)
|
||||
|
||||
def SetProbabilisticHelper() -> None:
|
||||
while True:
|
||||
chance = input(
|
||||
"Set flip chance as float between 0.0 and 1.0. (Leave empty to cancel)\n"
|
||||
).strip()
|
||||
if chance == "":
|
||||
print("Cancelled")
|
||||
return
|
||||
def SwitchToAsyncRandom() -> None:
|
||||
wasProbabilistic = boolNetwork.updateScheme == "probabilistic"
|
||||
boolNetwork.UseAsynchronousRandomScheme()
|
||||
if wasProbabilistic:
|
||||
AdoptFromProbabilistic()
|
||||
|
||||
try:
|
||||
chance = float(chance)
|
||||
boolNetwork.UseProbabilisticScheme(chance)
|
||||
return
|
||||
|
||||
except Exception as e:
|
||||
print("Invalid input:", e)
|
||||
def SwitchToProbabilistic() -> None:
|
||||
for i in range(boolNetwork.size):
|
||||
if not probFunctionStrings[i] and functions[i] is not None:
|
||||
boolNetwork.AddProbabilisticFunction(i, functions[i], 1.0)
|
||||
probFunctionStrings[i].append(functionStrings[i])
|
||||
boolNetwork.UseProbabilisticScheme()
|
||||
|
||||
title = "Select update scheme:"
|
||||
options = [
|
||||
@@ -282,15 +292,120 @@ def BooleanNetworkMenu(
|
||||
"Cancel",
|
||||
]
|
||||
actions = [
|
||||
lambda: boolNetwork.UseSynchronousScheme(),
|
||||
SwitchToSynchronous,
|
||||
SetSequentialHelper,
|
||||
SetProbabilisticHelper,
|
||||
lambda: boolNetwork.UseAsynchronousRandomScheme(),
|
||||
SwitchToProbabilistic,
|
||||
SwitchToAsyncRandom,
|
||||
lambda: None,
|
||||
]
|
||||
|
||||
actions[ShowMenu(options=options, title=title)]()
|
||||
|
||||
def FunctionsMenu() -> None:
|
||||
nonlocal functions_highlight
|
||||
done: bool = False
|
||||
|
||||
def Menu() -> None:
|
||||
nonlocal functions_highlight
|
||||
title = "Edit update functions:"
|
||||
deleteTargets: list = []
|
||||
|
||||
if boolNetwork.updateScheme in ("synchronous", "sequential", None):
|
||||
options = [
|
||||
*[
|
||||
f"Set update function of node x{i} (current: {functionStrings[i - 1]})"
|
||||
for i in range(1, boolNetwork.size + 1)
|
||||
],
|
||||
None,
|
||||
"Return",
|
||||
]
|
||||
actions = [
|
||||
*[partial(SetFunctionHelper, i) for i in range(boolNetwork.size)],
|
||||
None,
|
||||
ReturnHelper,
|
||||
]
|
||||
elif boolNetwork.updateScheme == "asynchronous_random":
|
||||
options = [
|
||||
*[
|
||||
f"Set update function of node x{i} (current: {functionStrings[i - 1]})"
|
||||
for i in range(1, boolNetwork.size + 1)
|
||||
],
|
||||
None,
|
||||
*[
|
||||
f"Set selection weight of node x{i} (current: {boolNetwork.node_selection_weights[i - 1]})"
|
||||
for i in range(1, boolNetwork.size + 1)
|
||||
],
|
||||
None,
|
||||
"Return",
|
||||
]
|
||||
actions = [
|
||||
*[partial(SetFunctionHelper, i) for i in range(boolNetwork.size)],
|
||||
None,
|
||||
*[partial(SetNodeWeightHelper, i) for i in range(boolNetwork.size)],
|
||||
None,
|
||||
ReturnHelper,
|
||||
]
|
||||
else: # probabilistic
|
||||
title = "Edit update functions:\n(highlight a function entry and press 'd' to delete it)"
|
||||
options = []
|
||||
actions = []
|
||||
for i in range(boolNetwork.size):
|
||||
for j in range(len(probFunctionStrings[i])):
|
||||
options.append(
|
||||
f"Set update function #{j + 1} of node x{i + 1} (current: {probFunctionStrings[i][j]})"
|
||||
)
|
||||
actions.append(partial(EditProbFunctionHelper, i, j))
|
||||
deleteTargets.append((i, j))
|
||||
options.append(
|
||||
f"Set weight of function #{j + 1} of node x{i + 1} (current: {boolNetwork.probabilistic_weights[i][j]})"
|
||||
)
|
||||
actions.append(partial(EditProbWeightHelper, i, j))
|
||||
deleteTargets.append(None)
|
||||
options.append(f"Add new function for node x{i + 1}")
|
||||
actions.append(partial(AddProbFunctionHelper, i))
|
||||
deleteTargets.append(None)
|
||||
options.append(None)
|
||||
actions.append(None)
|
||||
deleteTargets.append(None)
|
||||
options.append("Return")
|
||||
actions.append(ReturnHelper)
|
||||
deleteTargets.append(None)
|
||||
|
||||
if boolNetwork.updateScheme == "probabilistic":
|
||||
menu = TerminalMenu(
|
||||
menu_entries=options,
|
||||
title=title,
|
||||
multi_select=False,
|
||||
cursor_index=functions_highlight,
|
||||
accept_keys=("enter", "d"),
|
||||
)
|
||||
selectedIndex = menu.show()
|
||||
if selectedIndex is None:
|
||||
selectedIndex = len(options) - 1
|
||||
acceptKey = "enter"
|
||||
else:
|
||||
acceptKey = menu.chosen_accept_key
|
||||
functions_highlight = selectedIndex
|
||||
|
||||
if acceptKey == "d" and deleteTargets[selectedIndex] is not None:
|
||||
DeleteProbFunctionHelper(*deleteTargets[selectedIndex])
|
||||
else:
|
||||
actions[selectedIndex]()
|
||||
return
|
||||
|
||||
selectedIndex = ShowMenu(
|
||||
options=options, title=title, highlight_entry=functions_highlight
|
||||
)
|
||||
functions_highlight = selectedIndex
|
||||
actions[selectedIndex]()
|
||||
|
||||
def ReturnHelper() -> None:
|
||||
nonlocal done
|
||||
done = True
|
||||
|
||||
while not done:
|
||||
Menu()
|
||||
|
||||
def UpdateHelper() -> None:
|
||||
nonlocal functions, boolNetwork, functionsDirtyFlag
|
||||
if functionsDirtyFlag:
|
||||
@@ -377,6 +492,115 @@ def BooleanNetworkMenu(
|
||||
except Exception as e:
|
||||
print("Error while parsing function:", e)
|
||||
|
||||
def SetNodeWeightHelper(index: int) -> None:
|
||||
nonlocal boolNetwork
|
||||
while True:
|
||||
weight = input(
|
||||
f"Set new selection weight for node x{index + 1}. Must be a positive number. (Leave empty to cancel)\n"
|
||||
).strip()
|
||||
if weight == "":
|
||||
print("Cancelled")
|
||||
return
|
||||
try:
|
||||
weight = float(weight)
|
||||
boolNetwork.SetNodeSelectionWeight(index, weight)
|
||||
return
|
||||
except Exception as e:
|
||||
print("Invalid input:", e)
|
||||
|
||||
def AddProbFunctionHelper(index: int) -> None:
|
||||
nonlocal boolNetwork, probFunctionStrings
|
||||
while True:
|
||||
funcString = input(
|
||||
f"Set new function for node x{index + 1}. The function will receive all nodes in form of x1, x2, ..., x[size]. (Leave empty to cancel)\n"
|
||||
)
|
||||
if funcString == "":
|
||||
print("Cancelled")
|
||||
return
|
||||
try:
|
||||
func = (
|
||||
"lambda "
|
||||
+ ",".join(f"x{i}" for i in range(1, boolNetwork.size + 1))
|
||||
+ ":"
|
||||
+ funcString
|
||||
)
|
||||
func = eval(func)
|
||||
if not isinstance(func, FunctionType):
|
||||
print("Please enter a valid function. Got: " + func)
|
||||
continue
|
||||
except Exception as e:
|
||||
print("Error while parsing function:", e)
|
||||
continue
|
||||
|
||||
weight = 1.0
|
||||
weightInput = input(
|
||||
"Set weight for this function. Must be a positive number. (Leave empty for default 1.0)\n"
|
||||
).strip()
|
||||
if weightInput != "":
|
||||
try:
|
||||
weight = float(weightInput)
|
||||
except ValueError:
|
||||
print("Invalid weight, using default 1.0")
|
||||
weight = 1.0
|
||||
|
||||
try:
|
||||
boolNetwork.AddProbabilisticFunction(index, func, weight)
|
||||
probFunctionStrings[index].append(funcString)
|
||||
return
|
||||
except Exception as e:
|
||||
print("Error while adding function:", e)
|
||||
|
||||
def EditProbFunctionHelper(index: int, function_index: int) -> None:
|
||||
nonlocal boolNetwork, probFunctionStrings
|
||||
while True:
|
||||
funcString = input(
|
||||
f"Set new function for node x{index + 1}, function #{function_index + 1}. (Leave empty to cancel)\n"
|
||||
)
|
||||
if funcString == "":
|
||||
print("Cancelled")
|
||||
return
|
||||
try:
|
||||
func = (
|
||||
"lambda "
|
||||
+ ",".join(f"x{i}" for i in range(1, boolNetwork.size + 1))
|
||||
+ ":"
|
||||
+ funcString
|
||||
)
|
||||
func = eval(func)
|
||||
if not isinstance(func, FunctionType):
|
||||
print("Please enter a valid function. Got: " + func)
|
||||
continue
|
||||
boolNetwork.SetProbabilisticFunction(index, function_index, func)
|
||||
probFunctionStrings[index][function_index] = funcString
|
||||
return
|
||||
except Exception as e:
|
||||
print("Error while parsing function:", e)
|
||||
|
||||
def EditProbWeightHelper(index: int, function_index: int) -> None:
|
||||
nonlocal boolNetwork
|
||||
while True:
|
||||
weight = input(
|
||||
f"Set new weight for node x{index + 1}, function #{function_index + 1}. Must be a positive number. (Leave empty to cancel)\n"
|
||||
).strip()
|
||||
if weight == "":
|
||||
print("Cancelled")
|
||||
return
|
||||
try:
|
||||
weight = float(weight)
|
||||
boolNetwork.SetProbabilisticFunctionWeight(index, function_index, weight)
|
||||
return
|
||||
except Exception as e:
|
||||
print("Invalid input:", e)
|
||||
|
||||
def DeleteProbFunctionHelper(index: int, function_index: int) -> None:
|
||||
nonlocal boolNetwork, probFunctionStrings
|
||||
try:
|
||||
boolNetwork.RemoveProbabilisticFunction(index, function_index)
|
||||
del probFunctionStrings[index][function_index]
|
||||
except Exception as e:
|
||||
print("Error while deleting function:", e)
|
||||
Continue()
|
||||
|
||||
def ToggleWriteToFileHelper():
|
||||
nonlocal writeToFile
|
||||
writeToFile = not writeToFile
|
||||
|
||||
Reference in New Issue
Block a user