@@ -360,17 +360,79 @@ def _pauli_string_from_unit(unit: UnitPauliStringT, coefficient: Union[int, floa
360
360
class PauliSum :
361
361
"""Represents operator defined by linear combination of PauliStrings.
362
362
363
- Since PauliStrings store their own coefficients, this class
364
- does not implement the LinearDict interface. Instead, you can
363
+ Since `cirq.PauliString`s store their own coefficients, this class
364
+ does not implement the `cirq. LinearDict` interface. Instead, you can
365
365
add and subtract terms and then iterate over the resulting
366
366
(simplified) expression.
367
367
368
368
Under the hood, this class is backed by a LinearDict with coefficient-less
369
369
PauliStrings as keys. PauliStrings are reconstructed on-the-fly during
370
370
iteration.
371
+
372
+ PauliSums can be constructed explicitly:
373
+
374
+
375
+ >>> a, b = cirq.GridQubit.rect(1, 2)
376
+ >>> psum = cirq.PauliSum.from_pauli_strings([
377
+ ... cirq.PauliString(-1, cirq.X(a), cirq.Y(b)),
378
+ ... cirq.PauliString(2, cirq.Z(a), cirq.Z(b)),
379
+ ... cirq.PauliString(0.5, cirq.Y(a), cirq.Y(b))
380
+ ... ])
381
+ >>> print(psum)
382
+ -1.000*X(q(0))*Y(q(1))+2.000*Z(q(0))*Z(q(1))+0.500*Y(q(0))*Y(q(1))
383
+
384
+
385
+ or implicitly:
386
+
387
+
388
+ >>> a, b = cirq.GridQubit.rect(1, 2)
389
+ >>> psum = cirq.X(a) * cirq.X(b) + 3.0 * cirq.Y(a)
390
+ >>> psum
391
+ cirq.PauliSum(
392
+ cirq.LinearDict({
393
+ frozenset({
394
+ (cirq.GridQubit(0, 0), cirq.X), (cirq.GridQubit(0, 1), cirq.X)}): (1+0j),
395
+ frozenset({
396
+ (cirq.GridQubit(0, 0), cirq.Y)}): (3+0j)}
397
+ )
398
+ )
399
+
400
+
401
+ basic arithmetic and expectation operations are supported as well:
402
+
403
+
404
+ >>> a, b = cirq.GridQubit.rect(1, 2)
405
+ >>> psum = cirq.X(a) * cirq.X(b) + 3.0 * cirq.Y(a)
406
+ >>> two_psum = 2 * psum
407
+ >>> four_psum = two_psum + two_psum
408
+ >>> print(four_psum)
409
+ 4.000*X(q(0, 0))*X(q(0, 1))+12.000*Y(q(0, 0))
410
+
411
+
412
+ >>> expectation = four_psum.expectation_from_state_vector(
413
+ ... np.array([0.707106, 0, 0, 0.707106], dtype=complex),
414
+ ... qubit_map={a: 0, b: 1}
415
+ ... )
416
+ >>> expectation
417
+ 4.0
418
+
419
+
371
420
"""
372
421
373
422
def __init__ (self , linear_dict : Optional [value .LinearDict [UnitPauliStringT ]] = None ):
423
+ """Construct a PauliSum from a linear dictionary.
424
+
425
+ Note, the preferred method of constructing PauliSum objects is either implicitly
426
+ or via the `from_pauli_strings` function.
427
+
428
+ Args:
429
+ linear_dict: Set of (`cirq.Qid`, `cirq.Pauli`) tuples to construct the sum
430
+ from.
431
+
432
+ Raises:
433
+ ValueError: If structure of `linear_dict` contains tuples other than the
434
+ form (`cirq.Qid`, `cirq.Pauli`).
435
+ """
374
436
if linear_dict is None :
375
437
linear_dict = value .LinearDict ()
376
438
if not _is_linear_dict_of_unit_pauli_string (linear_dict ):
@@ -386,12 +448,39 @@ def _value_equality_values_(self):
386
448
387
449
@staticmethod
388
450
def wrap (val : PauliSumLike ) -> 'PauliSum' :
451
+ """Convert a `cirq.PauliSumLike` object to a PauliSum
452
+
453
+ Attemps to convert an existing int, float, complex, `cirq.PauliString`,
454
+ `cirq.PauliSum` or `cirq.SingleQubitPauliStringGateOperation` into
455
+ a `cirq.PauliSum` object. For example:
456
+
457
+
458
+ >>> my_psum = cirq.PauliSum.wrap(2.345)
459
+ >>> my_psum
460
+ cirq.PauliSum(cirq.LinearDict({frozenset(): (2.345+0j)}))
461
+
462
+
463
+ Args:
464
+ `cirq.PauliSumLike` to convert to PauliSum.
465
+
466
+ Returns:
467
+ PauliSum representation of `val`.
468
+ """
389
469
if isinstance (val , PauliSum ):
390
470
return val
391
471
return PauliSum () + val
392
472
393
473
@classmethod
394
474
def from_pauli_strings (cls , terms : Union [PauliString , List [PauliString ]]) -> 'PauliSum' :
475
+ """Returns a PauliSum by combining `cirq.PauliString` terms.
476
+
477
+ Args:
478
+ terms: `cirq.PauliString` or List of `cirq.PauliString`s to use inside
479
+ of this PauliSum object.
480
+ Returns:
481
+ PauliSum object representing the addition of all the `cirq.PauliString`
482
+ terms in `terms`.
483
+ """
395
484
if isinstance (terms , PauliString ):
396
485
terms = [terms ]
397
486
termdict : DefaultDict [UnitPauliStringT , value .Scalar ] = defaultdict (lambda : 0 )
@@ -414,7 +503,7 @@ def from_boolean_expression(
414
503
qubit_map: map of string (boolean variable name) to qubit.
415
504
416
505
Return:
417
- The PauliString that represents the Boolean expression.
506
+ The PauliSum that represents the Boolean expression.
418
507
419
508
Raises:
420
509
ValueError: If `boolean_expr` is of an unsupported type.
@@ -455,10 +544,25 @@ def from_boolean_expression(
455
544
456
545
@property
457
546
def qubits (self ) -> Tuple [raw_types .Qid , ...]:
547
+ """The sorted list of qubits used in this PauliSum."""
458
548
qs = {q for k in self ._linear_dict .keys () for q , _ in k }
459
549
return tuple (sorted (qs ))
460
550
461
551
def with_qubits (self , * new_qubits : 'cirq.Qid' ) -> 'PauliSum' :
552
+ """Return a new PauliSum on `new_qubits`.
553
+
554
+ Args:
555
+ *new_qubits: `cirq.Qid` objects to replace existing
556
+ qubit objects in this PauliSum.
557
+
558
+ Returns:
559
+ PauliSum with new_qubits replacing the previous
560
+ qubits.
561
+
562
+ Raises:
563
+ ValueError: If len(new_qubits) != len(self.qubits).
564
+
565
+ """
462
566
qubits = self .qubits
463
567
if len (new_qubits ) != len (qubits ):
464
568
raise ValueError ('Incorrect number of qubits for PauliSum.' )
@@ -469,12 +573,25 @@ def with_qubits(self, *new_qubits: 'cirq.Qid') -> 'PauliSum':
469
573
return PauliSum .from_pauli_strings (new_pauli_strings )
470
574
471
575
def copy (self ) -> 'PauliSum' :
576
+ """Return a copy of this PauliSum.
577
+
578
+ Returns: A copy of this PauliSum.
579
+ """
472
580
factory = type (self )
473
581
return factory (self ._linear_dict .copy ())
474
582
475
583
def matrix (self , qubits : Optional [Iterable [raw_types .Qid ]] = None ) -> np .ndarray :
476
- """Reconstructs matrix of self from underlying Pauli operations in
477
- computational basis of qubits.
584
+ """Returns the matrix of this PauliSum in computational basis of qubits.
585
+
586
+ Args:
587
+ qubits: Ordered collection of qubits that determine the subspace
588
+ in which the matrix representation of the Pauli sum is to
589
+ be computed. If none is provided the default ordering of
590
+ `self.qubits` is used. Qubits present in `qubits` but absent from
591
+ `self.qubits` are acted on by the identity.
592
+
593
+ Returns:
594
+ np.ndarray representing the matrix of this PauliSum expression.
478
595
479
596
Raises:
480
597
TypeError: if any of the gates in self does not provide a unitary.
0 commit comments