shukdevdatta123 commited on
Commit
bf0fc7f
·
verified ·
1 Parent(s): 78a3cee

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +72 -60
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
- def circuit_to_formula(circuit):
34
- # Convert the circuit to an equivalent formula.
35
- formula = nx.dag_to_branching(circuit)
36
- # Transfer the operator or variable labels for each node from the
37
- # circuit to the formula.
38
- for v in formula:
39
- source = formula.nodes[v]["source"]
40
- formula.nodes[v]["label"] = circuit.nodes[source]["label"]
41
- return formula
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
- # Let user input number of layers, nodes and edges for the circuit
123
- num_layers = st.number_input("Number of layers:", min_value=1, value=3)
124
- num_nodes = st.number_input("Number of nodes:", min_value=1, value=5)
125
- num_edges = st.number_input("Number of edges:", min_value=1, value=3)
126
-
127
- circuit = nx.DiGraph()
128
-
129
- # Allow user to input labels and edges
130
- for layer in range(num_layers):
131
- for node in range(num_nodes):
132
- label = st.text_input(f"Enter label for node ({layer}, {node}):", key=f"label_{layer}_{node}")
133
- circuit.add_node(f"{layer}_{node}", label=label, layer=layer)
134
-
135
- # Allow user to input edges between nodes
136
- edges = []
137
- for i in range(num_edges):
138
- source = st.text_input(f"Enter source node for edge {i+1} (e.g., '0_1')", key=f"source_edge_{i}")
139
- dest = st.text_input(f"Enter destination node for edge {i+1} (e.g., '1_2')", key=f"dest_edge_{i}")
140
- edges.append((source, dest))
141
- circuit.add_edges_from(edges)
142
-
143
- # Create the formula based on the circuit
144
- formula = circuit_to_formula(circuit)
145
- st.write("Formula: ", formula_to_string(formula))
146
-
147
- # Draw the circuit
148
- labels = nx.get_node_attributes(circuit, "label")
149
- options = {
150
- "node_size": 600,
151
- "alpha": 0.5,
152
- "node_color": "blue",
153
- "labels": labels,
154
- "font_size": 22,
155
- }
156
- plt.figure(figsize=(8, 8))
157
- pos = nx.multipartite_layout(circuit, subset_key="layer")
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":