quantumlib / Qualtran

Qᴜᴀʟᴛʀᴀɴ is a Python library for expressing and analyzing Fault Tolerant Quantum algorithms.
https://qualtran.readthedocs.io/en/latest/
Apache License 2.0
171 stars 40 forks source link

`show_call_graph(bloq)` doesn't work for bloqs with symbolic signature due to qubit count computation raising an error. #1298

Closed tanujkhattar closed 1 month ago

tanujkhattar commented 1 month ago
import sympy
from qualtran import QUInt
from qualtran.bloqs.arithmetic import Add
from qualtran.drawing import show_call_graph
n = sympy.symbols('n')
bloq = Add(QUInt(n))
g, _ = bloq.call_graph()
show_call_graph(g) # Works
show_call_graph(bloq) # Raises an error

Output of first call

image

Output of second call

``` --------------------------------------------------------------------------- TypeError Traceback (most recent call last) Cell In[16], line 9 7 g, _ = bloq.call_graph() 8 show_call_graph(g) # Works ----> 9 show_call_graph(bloq) # Raises an error File ~/quantum/Qualtran/qualtran/drawing/_show_funcs.py:117, in show_call_graph(item, max_depth, agg_gate_counts) 99 """Display a graph representation of the call graph. 100 101 Args: (...) 113 114 """ 115 if isinstance(item, Bloq): 116 IPython.display.display( --> 117 GraphvizCallGraph.from_bloq( 118 item, max_depth=max_depth, agg_gate_counts=agg_gate_counts 119 ).get_svg() 120 ) 121 else: 122 IPython.display.display(GraphvizCounts(item).get_svg()) File ~/quantum/Qualtran/qualtran/drawing/bloq_counts_graph.py:330, in GraphvizCallGraph.from_bloq(cls, bloq, max_depth, agg_gate_counts) 327 from qualtran.resource_counting import QECGatesCost, QubitCount, query_costs 329 call_graph, _ = bloq.call_graph(max_depth=max_depth) --> 330 cost_data: Dict['Bloq', Dict[CostKey, Any]] = query_costs( 331 bloq, [QubitCount(), QECGatesCost()] 332 ) 333 formatted_cost_data = cls.format_cost_data(cost_data, agg_gate_counts=agg_gate_counts) 334 return cls(g=call_graph, bloq_data=formatted_cost_data) File ~/quantum/Qualtran/qualtran/resource_counting/_costing.py:246, in query_costs(bloq, cost_keys, generalizer) 244 costs: Dict['Bloq', Dict[CostKey, CostValT]] = defaultdict(dict) 245 for cost_key in cost_keys: --> 246 cost_for_bloqs = get_cost_cache(bloq, cost_key, generalizer=generalizer) 247 for bloq, val in cost_for_bloqs.items(): 248 costs[bloq][cost_key] = val File ~/quantum/Qualtran/qualtran/resource_counting/_costing.py:217, in get_cost_cache(bloq, cost_key, costs_cache, generalizer) 214 if isinstance(generalizer, collections.abc.Sequence): 215 generalizer = _make_composite_generalizer(*generalizer) --> 217 _get_cost_value(bloq, cost_key, costs_cache=costs_cache, generalizer=generalizer) 218 return costs_cache File ~/quantum/Qualtran/qualtran/resource_counting/_costing.py:144, in _get_cost_value(bloq, cost_key, costs_cache, generalizer) 142 # part b. call the compute method and cache the result. 143 tstart = time.perf_counter() --> 144 computed_cost = cost_key.compute(bloq, _get_cost_val_internal) 145 tdur = time.perf_counter() - tstart 146 logger.info("Computed %s for %s in %g s", cost_key, bloq, tdur) File ~/quantum/Qualtran/qualtran/resource_counting/_qubit_counts.py:105, in QubitCount.compute(self, bloq, get_callee_cost) 100 """Compute an estimate of the number of qubits used by `bloq`. 101 102 See the class docstring for more information. 103 """ 104 # Base case: No callees; use the signature --> 105 min_bloq_size = bloq.signature.n_qubits() 106 callees = get_bloq_callee_counts(bloq) 107 if len(callees) == 0: File ~/quantum/Qualtran/qualtran/_infra/registers.py:207, in Signature.n_qubits(self) 205 left_size = sum(reg.total_bits() for reg in self.lefts()) 206 right_size = sum(reg.total_bits() for reg in self.rights()) --> 207 return max(left_size, right_size) File ~/opt/anaconda3/envs/qualtran2/lib/python3.11/site-packages/sympy/core/relational.py:510, in Relational.__bool__(self) 509 def __bool__(self): --> 510 raise TypeError("cannot determine truth value of Relational") TypeError: cannot determine truth value of Relational ```
anurudhp commented 1 month ago

related: #1261