Update app.py
Browse files
app.py
CHANGED
|
@@ -30,34 +30,50 @@ def draw_graph(G, pos=None, title="Graph Visualization"):
|
|
| 30 |
nx.draw(G, pos=pos, with_labels=True, node_color='lightblue', node_size=500, font_size=10, font_weight='bold')
|
| 31 |
st.pyplot(plt)
|
| 32 |
|
| 33 |
-
|
| 34 |
-
|
| 35 |
-
|
| 36 |
-
|
| 37 |
-
|
| 38 |
-
|
| 39 |
-
|
| 40 |
-
|
| 41 |
-
|
| 42 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 43 |
def formula_to_string(formula):
|
| 44 |
def _to_string(formula, root):
|
| 45 |
-
# If there are no children, this is a variable node.
|
| 46 |
label = formula.nodes[root]["label"]
|
| 47 |
if not formula[root]:
|
| 48 |
return label
|
| 49 |
-
# Otherwise, this is an operator.
|
| 50 |
children = formula[root]
|
| 51 |
-
# If one child, the label must be a NOT operator.
|
| 52 |
if len(children) == 1:
|
| 53 |
child = nx.utils.arbitrary_element(children)
|
| 54 |
return f"{label}({_to_string(formula, child)})"
|
| 55 |
-
# NB "left" and "right" here are a little misleading: there is
|
| 56 |
-
# no order on the children of a node. That's okay because the
|
| 57 |
-
# Boolean AND and OR operators are symmetric. It just means that the
|
| 58 |
-
# order of the operands cannot be predicted and hence the
|
| 59 |
-
# function does not necessarily behave the same way on every
|
| 60 |
-
# invocation.
|
| 61 |
left, right = formula[root]
|
| 62 |
left_subformula = _to_string(formula, left)
|
| 63 |
right_subformula = _to_string(formula, right)
|
|
@@ -77,7 +93,7 @@ def algorithms_circuits():
|
|
| 77 |
)
|
| 78 |
|
| 79 |
if circuit_mode == "Default Example":
|
| 80 |
-
# Define the default circuit
|
| 81 |
circuit = nx.DiGraph()
|
| 82 |
# Layer 0
|
| 83 |
circuit.add_node(0, label="∧", layer=0)
|
|
@@ -119,46 +135,42 @@ def algorithms_circuits():
|
|
| 119 |
elif circuit_mode == "Create Your Own":
|
| 120 |
st.write("### Create Your Own Circuit")
|
| 121 |
|
| 122 |
-
#
|
| 123 |
-
|
| 124 |
-
|
| 125 |
-
|
| 126 |
-
|
| 127 |
-
|
| 128 |
-
|
| 129 |
-
|
| 130 |
-
|
| 131 |
-
|
| 132 |
-
|
| 133 |
-
|
| 134 |
-
|
| 135 |
-
|
| 136 |
-
|
| 137 |
-
|
| 138 |
-
|
| 139 |
-
|
| 140 |
-
|
| 141 |
-
|
| 142 |
-
|
| 143 |
-
|
| 144 |
-
|
| 145 |
-
|
| 146 |
-
|
| 147 |
-
|
| 148 |
-
|
| 149 |
-
|
| 150 |
-
|
| 151 |
-
|
| 152 |
-
|
| 153 |
-
|
| 154 |
-
|
| 155 |
-
|
| 156 |
-
|
| 157 |
-
|
| 158 |
-
nx.draw_networkx(circuit, pos, **options)
|
| 159 |
-
plt.title(formula_to_string(formula))
|
| 160 |
-
plt.axis("equal")
|
| 161 |
-
st.pyplot()
|
| 162 |
|
| 163 |
# Display the corresponding page based on sidebar option
|
| 164 |
if sidebar_option == "Algorithms: Circuits":
|
|
|
|
| 30 |
nx.draw(G, pos=pos, with_labels=True, node_color='lightblue', node_size=500, font_size=10, font_weight='bold')
|
| 31 |
st.pyplot(plt)
|
| 32 |
|
| 33 |
+
# Function to convert a sympy Boolean expression to a graph
|
| 34 |
+
def formula_to_circuit(formula):
|
| 35 |
+
circuit = nx.DiGraph()
|
| 36 |
+
node_id = 0
|
| 37 |
+
def add_formula_node(expr):
|
| 38 |
+
nonlocal node_id
|
| 39 |
+
# Create a unique node for each part of the formula
|
| 40 |
+
current_node = node_id
|
| 41 |
+
node_id += 1
|
| 42 |
+
circuit.add_node(current_node, label=str(expr))
|
| 43 |
+
return current_node
|
| 44 |
+
|
| 45 |
+
def build_circuit(expr):
|
| 46 |
+
if isinstance(expr, symbols):
|
| 47 |
+
# It's a variable, just return it as a node
|
| 48 |
+
return add_formula_node(expr)
|
| 49 |
+
elif isinstance(expr, Not):
|
| 50 |
+
# NOT operator
|
| 51 |
+
child = build_circuit(expr.args[0])
|
| 52 |
+
current_node = add_formula_node("¬")
|
| 53 |
+
circuit.add_edge(current_node, child)
|
| 54 |
+
return current_node
|
| 55 |
+
elif isinstance(expr, Or) or isinstance(expr, And):
|
| 56 |
+
# OR/AND operators
|
| 57 |
+
left = build_circuit(expr.args[0])
|
| 58 |
+
right = build_circuit(expr.args[1])
|
| 59 |
+
current_node = add_formula_node(str(expr.func))
|
| 60 |
+
circuit.add_edge(current_node, left)
|
| 61 |
+
circuit.add_edge(current_node, right)
|
| 62 |
+
return current_node
|
| 63 |
+
|
| 64 |
+
build_circuit(formula)
|
| 65 |
+
return circuit
|
| 66 |
+
|
| 67 |
+
# Function to convert a formula graph to a string for display
|
| 68 |
def formula_to_string(formula):
|
| 69 |
def _to_string(formula, root):
|
|
|
|
| 70 |
label = formula.nodes[root]["label"]
|
| 71 |
if not formula[root]:
|
| 72 |
return label
|
|
|
|
| 73 |
children = formula[root]
|
|
|
|
| 74 |
if len(children) == 1:
|
| 75 |
child = nx.utils.arbitrary_element(children)
|
| 76 |
return f"{label}({_to_string(formula, child)})"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 77 |
left, right = formula[root]
|
| 78 |
left_subformula = _to_string(formula, left)
|
| 79 |
right_subformula = _to_string(formula, right)
|
|
|
|
| 93 |
)
|
| 94 |
|
| 95 |
if circuit_mode == "Default Example":
|
| 96 |
+
# Define the default circuit as before
|
| 97 |
circuit = nx.DiGraph()
|
| 98 |
# Layer 0
|
| 99 |
circuit.add_node(0, label="∧", layer=0)
|
|
|
|
| 135 |
elif circuit_mode == "Create Your Own":
|
| 136 |
st.write("### Create Your Own Circuit")
|
| 137 |
|
| 138 |
+
# Text input for the Boolean expression
|
| 139 |
+
boolean_expression = st.text_input("Enter a Boolean expression (e.g., ((x ∨ y) ∧ (y ∨ ¬(z)))):")
|
| 140 |
+
|
| 141 |
+
# Generate button
|
| 142 |
+
if st.button("Generate Circuit"):
|
| 143 |
+
if boolean_expression:
|
| 144 |
+
try:
|
| 145 |
+
# Parse the input expression
|
| 146 |
+
expr = eval(boolean_expression, {}, {"Or": Or, "And": And, "Not": Not, "x": symbols('x'), "y": symbols('y'), "z": symbols('z')})
|
| 147 |
+
|
| 148 |
+
# Convert the formula to a circuit
|
| 149 |
+
circuit = formula_to_circuit(expr)
|
| 150 |
+
|
| 151 |
+
# Display the formula as a string
|
| 152 |
+
st.write("Formula: ", formula_to_string(circuit))
|
| 153 |
+
|
| 154 |
+
# Visualize the circuit
|
| 155 |
+
labels = nx.get_node_attributes(circuit, "label")
|
| 156 |
+
options = {
|
| 157 |
+
"node_size": 600,
|
| 158 |
+
"alpha": 0.5,
|
| 159 |
+
"node_color": "blue",
|
| 160 |
+
"labels": labels,
|
| 161 |
+
"font_size": 22,
|
| 162 |
+
}
|
| 163 |
+
plt.figure(figsize=(8, 8))
|
| 164 |
+
pos = nx.multipartite_layout(circuit, subset_key="layer")
|
| 165 |
+
nx.draw_networkx(circuit, pos, **options)
|
| 166 |
+
plt.title(formula_to_string(circuit))
|
| 167 |
+
plt.axis("equal")
|
| 168 |
+
st.pyplot()
|
| 169 |
+
|
| 170 |
+
except Exception as e:
|
| 171 |
+
st.error(f"Error parsing the expression: {e}")
|
| 172 |
+
else:
|
| 173 |
+
st.error("Please enter a valid Boolean expression.")
|
|
|
|
|
|
|
|
|
|
|
|
|
| 174 |
|
| 175 |
# Display the corresponding page based on sidebar option
|
| 176 |
if sidebar_option == "Algorithms: Circuits":
|