2323import numpy as np
2424
2525import pennylane as qml
26+ from pennylane import math
2627from pennylane .exceptions import QuantumFunctionError
2728from pennylane .measurements import (
2829 CountsMP ,
@@ -236,18 +237,18 @@ def _measurement_with_no_shots(measurement):
236237
237238def _get_is_valid_has_valid (mcm_samples , all_mcms , interface ):
238239 # Can't use boolean dtype array with tf, hence why conditionally setting items to 0 or 1
239- has_postselect = qml . math .array (
240+ has_postselect = math .array (
240241 [[op .postselect is not None for op in all_mcms ]],
241242 like = interface ,
242243 dtype = mcm_samples .dtype ,
243244 )
244- postselect = qml . math .array (
245+ postselect = math .array (
245246 [[0 if op .postselect is None else op .postselect for op in all_mcms ]],
246247 like = interface ,
247248 dtype = mcm_samples .dtype ,
248249 )
249- is_valid = qml . math .all (mcm_samples * has_postselect == postselect , axis = 1 )
250- has_valid = qml . math .any (is_valid )
250+ is_valid = math .all (mcm_samples * has_postselect == postselect , axis = 1 )
251+ has_valid = math .any (is_valid )
251252 return is_valid , has_valid
252253
253254
@@ -270,15 +271,15 @@ def parse_native_mid_circuit_measurements(
270271 tuple(TensorLike): The results of the simulation.
271272 """
272273 assert results is not None # condition needed to not break signature
273- interface = qml . math .get_deep_interface (results )
274+ interface = math .get_deep_interface (results )
274275 interface = "numpy" if interface == "builtins" else interface
275276 interface = "tensorflow" if interface == "tf" else interface
276277
277278 all_mcms = [op for op in circuit .operations if is_mcm (op )]
278- mcm_samples = qml . math .hstack (
279- tuple (qml . math .reshape (qml . math .vstack (res ), (- 1 , 1 )) for res in results [- len (all_mcms ) :])
279+ mcm_samples = math .hstack (
280+ tuple (math .reshape (math .vstack (res ), (- 1 , 1 )) for res in results [- len (all_mcms ) :])
280281 )
281- mcm_samples = qml . math .array (mcm_samples , like = interface )
282+ mcm_samples = math .array (mcm_samples , like = interface )
282283
283284 is_valid , has_valid = _get_is_valid_has_valid (mcm_samples , all_mcms , interface )
284285
@@ -327,10 +328,10 @@ def _handle_measurement_qjit(
327328 if isinstance (m , CountsMP ):
328329 res = (
329330 result [0 ][0 ],
330- qml . math .sum (result [1 ] * qml . math .reshape (is_valid , (- 1 , 1 )), axis = 0 ),
331+ math .sum (result [1 ] * math .reshape (is_valid , (- 1 , 1 )), axis = 0 ),
331332 )
332333 return res , m_count + 1
333- result = qml . math .squeeze (result )
334+ result = math .squeeze (result )
334335 return gather_non_mcm (m , result , is_valid , postselect_mode = postselect_mode ), m_count + 1
335336
336337
@@ -375,17 +376,17 @@ def gather_mcm_qjit(measurement, samples, is_valid, postselect_mode=None): # pr
375376 break
376377 if not found :
377378 raise LookupError ("MCM not found" )
378- meas = qml . math .squeeze (meas )
379+ meas = math .squeeze (meas )
379380 if isinstance (measurement , (CountsMP , ProbabilityMP )):
380- interface = qml . math .get_interface (is_valid )
381- sum_valid = qml . math .sum (is_valid )
382- count_1 = qml . math .sum (meas * is_valid )
381+ interface = math .get_interface (is_valid )
382+ sum_valid = math .sum (is_valid )
383+ count_1 = math .sum (meas * is_valid )
383384 if isinstance (measurement , CountsMP ):
384- return qml . math .array ([0 , 1 ], like = interface ), qml . math .array (
385+ return math .array ([0 , 1 ], like = interface ), math .array (
385386 [sum_valid - count_1 , count_1 ], like = interface
386387 )
387388 if isinstance (measurement , ProbabilityMP ):
388- counts = qml . math .array ([sum_valid - count_1 , count_1 ], like = interface )
389+ counts = math .array ([sum_valid - count_1 , count_1 ], like = interface )
389390 return counts / sum_valid
390391 return gather_non_mcm (measurement , meas , is_valid , postselect_mode = postselect_mode )
391392
@@ -433,63 +434,61 @@ def _gather_counts(measurement: CountsMP, samples, is_valid, postselect_mode=Non
433434
434435@gather_non_mcm .register
435436def _gather_samples (measurement : SampleMP , samples , is_valid , postselect_mode = None ):
436- samples = qml . math .concatenate (samples ) if isinstance (samples , (list , tuple )) else samples
437+ samples = math .concatenate (samples ) if isinstance (samples , (list , tuple )) else samples
437438 if postselect_mode == "pad-invalid-samples" and samples .ndim == 2 :
438- is_valid = qml . math .reshape (is_valid , (- 1 , 1 ))
439+ is_valid = math .reshape (is_valid , (- 1 , 1 ))
439440 if postselect_mode == "pad-invalid-samples" :
440- return qml . math .where (is_valid , samples , fill_in_value )
441+ return math .where (is_valid , samples , fill_in_value )
441442 return samples [is_valid ]
442443
443444
444445# pylint: disable=unused-arguement
445446@gather_non_mcm .register
446447def _gather_expval (measurement : ExpectationMP , samples , is_valid , postselect_mode = None ):
447- samples = qml . math .stack (samples )
448+ samples = math .stack (samples )
448449 if (
449- qml . math .get_interface (is_valid ) == "tensorflow"
450+ math .get_interface (is_valid ) == "tensorflow"
450451 ): # pragma: no cover (TensorFlow tests were disabled during deprecation)
451452 # Tensorflow requires arrays that are used for arithmetic with each other to have the
452453 # same dtype. We don't cast if measuring samples as float tf.Tensors cannot be used to
453454 # index other tf.Tensors (is_valid is used to index valid samples).
454- is_valid = qml . math .cast_like (is_valid , samples )
455- return qml . math .sum (qml . math .squeeze (samples ) * is_valid ) / qml . math .sum (is_valid )
455+ is_valid = math .cast_like (is_valid , samples )
456+ return math .sum (math .squeeze (samples ) * is_valid ) / math .sum (is_valid )
456457
457458
458459# pylint: disable=unused-arguement
459460@gather_non_mcm .register
460461def _gather_probability (measurement : ProbabilityMP , samples , is_valid , postselect_mode = None ):
461- samples = qml . math .stack (samples , axis = 0 )
462+ samples = math .stack (samples , axis = 0 )
462463 if (
463- qml . math .get_interface (is_valid ) == "tensorflow"
464+ math .get_interface (is_valid ) == "tensorflow"
464465 ): # pragma: no cover (TensorFlow tests were disabled during deprecation)
465466 # Tensorflow requires arrays that are used for arithmetic with each other to have the
466467 # same dtype. We don't cast if measuring samples as float tf.Tensors cannot be used to
467468 # index other tf.Tensors (is_valid is used to index valid samples).
468- is_valid = qml .math .cast_like (is_valid , samples )
469- return qml .math .sum (samples * qml .math .reshape (is_valid , (- 1 , 1 )), axis = 0 ) / qml .math .sum (
470- is_valid
471- )
469+ is_valid = math .cast_like (is_valid , samples )
470+ return math .sum (samples * math .reshape (is_valid , (- 1 , 1 )), axis = 0 ) / math .sum (is_valid )
472471
473472
474473@gather_non_mcm .register
475474def _gather_variance (measurement : VarianceMP , samples , is_valid , postselect_mode = None ):
476- samples = qml . math .stack (samples )
475+ samples = math .stack (samples )
477476 if (
478- interface := qml . math .get_interface (is_valid )
477+ interface := math .get_interface (is_valid )
479478 ) == "tensorflow" : # pragma: no cover (TensorFlow tests were disabled during deprecation)
480479 # Tensorflow requires arrays that are used for arithmetic with each other to have the
481480 # same dtype. We don't cast if measuring samples as float tf.Tensors cannot be used to
482481 # index other tf.Tensors (is_valid is used to index valid samples).
483- is_valid = qml . math .cast_like (is_valid , samples )
484- samples = qml . math .squeeze (samples )
485- expval = qml . math .sum (samples * is_valid ) / qml . math .sum (is_valid )
482+ is_valid = math .cast_like (is_valid , samples )
483+ samples = math .squeeze (samples )
484+ expval = math .sum (samples * is_valid ) / math .sum (is_valid )
486485 if (
487486 interface == "tensorflow"
488487 ): # pragma: no cover (TensorFlow tests were disabled during deprecation)
489488 # Casting needed for tensorflow
490- samples = qml . math .cast_like (samples , expval )
491- is_valid = qml . math .cast_like (is_valid , expval )
492- return qml . math .sum ((samples - expval ) ** 2 * is_valid ) / qml . math .sum (is_valid )
489+ samples = math .cast_like (samples , expval )
490+ is_valid = math .cast_like (is_valid , expval )
491+ return math .sum ((samples - expval ) ** 2 * is_valid ) / math .sum (is_valid )
493492
494493
495494def gather_mcm (measurement : MeasurementProcess , samples , is_valid , postselect_mode = None ):
@@ -505,44 +504,42 @@ def gather_mcm(measurement: MeasurementProcess, samples, is_valid, postselect_mo
505504 TensorLike: The combined measurement outcome
506505 """
507506
508- interface = qml . math .get_deep_interface (is_valid )
507+ interface = math .get_deep_interface (is_valid )
509508 mv = measurement .mv
510509 # The following block handles measurement value lists, like ``qml.counts(op=[mcm0, mcm1, mcm2])``.
511510 if isinstance (measurement , (CountsMP , ProbabilityMP , SampleMP )) and isinstance (mv , Sequence ):
512511 mcm_samples = [m .concretize (samples ) for m in mv ]
513- mcm_samples = qml . math .concatenate (mcm_samples , axis = 1 )
512+ mcm_samples = math .concatenate (mcm_samples , axis = 1 )
514513 if isinstance (measurement , ProbabilityMP ):
515514 values = [list (m .branches .values ()) for m in mv ]
516515 values = list (itertools .product (* values ))
517- values = [qml . math .array ([v ], like = interface , dtype = mcm_samples .dtype ) for v in values ]
516+ values = [math .array ([v ], like = interface , dtype = mcm_samples .dtype ) for v in values ]
518517 # Need to use boolean functions explicitly as Tensorflow does not allow integer math
519518 # on boolean arrays
520519 counts = [
521- qml .math .count_nonzero (
522- qml .math .logical_and (qml .math .all (mcm_samples == v , axis = 1 ), is_valid )
523- )
520+ math .count_nonzero (math .logical_and (math .all (mcm_samples == v , axis = 1 ), is_valid ))
524521 for v in values
525522 ]
526- counts = qml . math .array (counts , like = interface )
527- return counts / qml . math .sum (counts )
523+ counts = math .array (counts , like = interface )
524+ return counts / math .sum (counts )
528525 if isinstance (measurement , CountsMP ):
529526 mcm_samples = [{"" .join (str (int (v )) for v in tuple (s )): 1 } for s in mcm_samples ]
530527 return gather_non_mcm (measurement , mcm_samples , is_valid , postselect_mode = postselect_mode )
531528
532- mcm_samples = qml . math .array (mv .concretize (samples ), like = interface )
529+ mcm_samples = math .array (mv .concretize (samples ), like = interface )
533530 if isinstance (measurement , ProbabilityMP ):
534531 # Need to use boolean functions explicitly as Tensorflow does not allow integer math
535532 # on boolean arrays
536- mcm_samples = qml . math .squeeze (mcm_samples )
533+ mcm_samples = math .squeeze (mcm_samples )
537534 counts = [
538- qml . math .count_nonzero (qml . math .logical_and ((mcm_samples == v ), is_valid ))
535+ math .count_nonzero (math .logical_and ((mcm_samples == v ), is_valid ))
539536 for v in list (mv .branches .values ())
540537 ]
541- counts = qml . math .array (counts , like = interface )
542- return counts / qml . math .sum (counts )
538+ counts = math .array (counts , like = interface )
539+ return counts / math .sum (counts )
543540 if isinstance (measurement , CountsMP ):
544- mcm_samples = [{float (s ): 1 } for s in mcm_samples ]
541+ mcm_samples = [{float (s . item () ): 1 } for s in mcm_samples ]
545542 results = gather_non_mcm (measurement , mcm_samples , is_valid , postselect_mode = postselect_mode )
546543 if isinstance (measurement , SampleMP ):
547- results = qml . math .squeeze (results )
544+ results = math .squeeze (results )
548545 return results
0 commit comments