a Ò"¯hô.ã@s¢dZddlmZddlZddlZddlmZddlm Z ddl m Z ddl m Z mZddlmZdd „Zd d „Zd d „Zddd„Zeedƒƒdd„ƒZdd„ZdS)a& ******************************************************************************** * Copyright (c) 2025 the Qrisp authors * * This program and the accompanying materials are made available under the * terms of the Eclipse Public License 2.0 which is available at * http://www.eclipse.org/legal/epl-2.0. * * This Source Code may also be made available under the following Secondary * Licenses when the conditions for such availability set forth in the Eclipse * Public License, v. 2.0 are satisfied: GNU General Public License, version 2 * with the GNU Classpath Exception which is * available at https://www.gnu.org/software/classpath/license.html. * * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 ******************************************************************************** é)Ú lru_cacheN)Ú ClosedJaxpr)ÚOperationPrimitive)Úmake_profiling_eqn_evaluatorÚ eval_jaxpr©Úsimulate_jasprcs‡fdd„}|S)aL Decorator to determine resources of large scale quantum computations. This decorator compiles the given Jasp-compatible function into a classical function computing the amount of each gates required. The decorated function will return a dictionary containing the operation counts. For many algorithms including classical feedback, the result of the measurements can heavily influence the required resources. To reflect this, users can specify the behavior of measurements during the computation of resources. The following strategies are available: * ``"0"`` - computes the resource as if measurements always return 0 * ``"1"`` - computes the resource as if measurements always return 1 * *callable* - allows the user to specify a random number generator (see examples) For more details on how the *callable* option can be used, consult the examples section. Finally it is also possible to call the Qrisp simulator to determine measurement behavior by providing ``sim``. This is of course much less scalable but in particular for algorithms involving repeat-until-success components, a necessary evil. Note that the ``sim`` option might return non-deterministic results, while the other methods do. .. warning:: It is currently not possible to estimate programs, which include a :ref:`kernelized ` function. Parameters ---------- meas_behavior : str or callable A string or callable indicating the behavior of the ressource computation when measurements are performed. Available are Returns ------- resource_estimation decorator A decorator, producing a function to computed the required resources. Examples -------- We compute the resources required to perform a large scale integer multiplication. :: from qrisp import count_ops, QuantumFloat, measure @count_ops(meas_behavior = "0") def main(i): a = QuantumFloat(i) b = QuantumFloat(i) c = a*b return measure(c) print(main(5)) # {'cx': 506, 'x': 22, 'h': 135, 'measure': 55, '2cx': 2, 's': 45, 't': 90, 't_dg': 90} print(main(5000)) # {'cx': 462552491, 'x': 20002, 'h': 112522500, 'measure': 37517500, '2cx': 2, 's': 37507500, 't': 75015000, 't_dg': 75015000} Note that even though the second computation contains more than 800 million gates, determining the resources takes less than 200ms, highlighting the scalability features of the Jasp infrastructure. **Modifying the measurement behavior via a random number generator** To specify the behavior, we specify an RNG function (for more details on what that means please check the `Jax documentation `_. This RNG takes as input a "key" and returns a boolean value. In this case, the return value will be uniformly distributed among True and False. :: from jax import random import jax.numpy as jnp from qrisp import QuantumFloat, measure, control, count_ops, x # Returns a uniformly distributed boolean def meas_behavior(key): return jnp.bool(random.randint(key, (1,), 0,1)[0]) @count_ops(meas_behavior = meas_behavior) def main(i): qv = QuantumFloat(2) meas_res = measure(qv) with control(meas_res == i): x(qv) return measure(qv) This script executes two measurements and based on the measurement outcome executes two X gates. We can now execute this resource computation with different values of ``i`` to see, which measurements return ``True`` with our given random-number generator (recall that this way of specifying the measurement behavior is fully deterministic). :: print(main(0)) # Yields: {'measure': 4, 'x': 2} print(main(1)) # Yields: {'measure': 4} print(main(2)) # Yields: {'measure': 4} print(main(3)) # Yields: {'measure': 4} From this we conclude that our RNG returned 0 for both of the initial measurements. For some algorithms (such as :ref:`RUS`) sampling the measurement result from a simple distribution won't cut it because the required ressource can be heavily influenced by measurement outcomes. For this matter it is also possible to perform a full simulation. Note that this simulation is no longer deterministic. :: @count_ops(meas_behavior = "sim") def main(i): qv = QuantumFloat(2) meas_res = measure(qv) with control(meas_res == i): x(qv) return measure(qv) print(main(0)) {'measure': 4, 'x': 2} print(main(1)) {'measure': 4} cs‡‡fdd„}|S)Ncshddlm}tˆdƒsiˆ_t|ƒ}tdd„|Dƒƒ}|ˆjvrR|ˆƒ|Žˆj|<ˆj|j|dˆiŽS)Nr)Ú make_jasprÚ jaspr_dictcSsg|] }t|ƒ‘qS©)Útype)Ú.0Úargr r ú[/Users/natalie/Documents/masters/GDP/code/first_try/qrisp/jasp/evaluation_tools/profiler.pyÚ ÐózOcount_ops..count_ops_decorator..ops_counter..Ú meas_behavior)Ú qrisp.jaspr Úhasattrr ÚlistÚtupleÚ count_ops)Úargsr Ú signature)Úfunctionrr rÚ ops_counterÇs    ÿÿz;count_ops..count_ops_decorator..ops_counterr )rr©r)rrÚcount_ops_decoratorÅsz&count_ops..count_ops_decoratorr )rrr rrr0s rcCsdS)NFr ©Úkeyr r rÚ always_zeroÝsr cCsdS)NTr rr r rÚ always_oneásr!Ú0csdtˆtƒr<ˆdkrt‰n$ˆdkr&t‰nˆdks.profilercstˆg|¢RddiŽS)NÚreturn_gate_countsTr)r)r0r rr1s)Ú isinstanceÚstrr r!Ú ExceptionÚcallable)r0rr1r r/rÚ profile_jasprès ÿ r7gjø@c sØt|ƒ}i‰tt|ƒƒD]Œ}t||tƒr~||j}|jrRt|j ¡  ¡  ¡ƒ}n|j g}|D]}|ˆvr^tˆƒdˆ|<q^q||j dkrdˆvrtˆƒdˆd<qt ˆ|ƒ}t  t||d¡‰‡‡fdd„}|ˆfS)Nr%z jasp.measureÚmeasure)Ú eqn_evaluatorcs6dgtˆƒttddƒƒf}t|ƒ|g}ˆ|Ž}|S)Nrr%é)r(rÚrange)rZ final_argÚres©Ú evaluatorr-r rr,3s z>get_profiling_array_computer..profiling_array_computer)Úget_primitivesr;r(r3rÚopÚ definitionrÚ transpilerr*ÚnamerÚjaxÚjitr) r0rÚ primitivesÚir@Zop_namesrCÚprofiling_eqn_evaluatorr,r r=rr's& ÿr'cCs’tƒ}|jD]|}| |j¡|jjdkr^| t|jddjƒ¡| t|jddjƒ¡q |j  ¡D]}t |t ƒrh| t|jƒ¡qhq t |ƒS)NÚcondÚbranchesrr%) ÚsetÚeqnsÚaddÚ primitiverCÚupdater?ÚparamsÚjaxprÚvaluesr3rr)rQrFÚeqnÚparamr r rr?Ks    r?)r")Ú__doc__Ú functoolsrÚnumpyÚnprDÚ jax.numpyÚjnpZjax.extend.corerÚqrisp.jasp.primitivesrÚqrisp.jasp.interpreter_toolsrrÚ)qrisp.jasp.evaluation_tools.jaspificationrrr r!r7r+r'r?r r r rÚs "     . /  3