This resource function is obsolete. Use the paclet Wolfram/QuantumFramework instead.

Function Repository Resource:

QuantumPartialTrace

Source Notebook

Partially trace out specified subsystems of a quantum basis, state or operator

Contributed by: Jonathan Gorard

ResourceFunction["QuantumPartialTrace"][QuantumBasis[],order]

returns the specified QuantumBasis object with the subsystems indexed by order traced out.

ResourceFunction["QuantumPartialTrace"][QuantumDiscreteState[],order]

returns the specified QuantumDiscreteState object with the subsystems indexed by order traced out.

ResourceFunction["QuantumPartialTrace"][QuantumDiscreteOperator[],order]

returns the specified QuantumDiscreteOperator object with the subsystems indexed by order traced out.

ResourceFunction["QuantumPartialTrace"][QuantumMeasurementOperator[],order]

returns the specified QuantumMeasurementOperator object with the subsystems indexed by order traced out.

ResourceFunction["QuantumPartialTrace"][QuantumHamiltonianOperator[],order]

returns the specified QuantumHamiltonianOperator object with the subsystems indexed by order traced out.

ResourceFunction["QuantumPartialTrace"][QuantumCircuitOperator[],order]

returns the (operator representation of the) specified QuantumCircuitOperator object with the subsystems indexed by order traced out.

Details

ResourceFunction["QuantumPartialTrace"] will return a QuantumBasis object if its first argument is a QuantumBasis object, a QuantumDiscreteState object if its first argument is a QuantumDiscreteState object, etc. The only exception to this rule is the QuantumCircuitOperator object, whose partial trace is always a QuantumDiscreteOperator object (i.e. ResourceFunction["QuantumPartialTrace"] always returns the operator representation of the resulting circuit).
ResourceFunction["QuantumPartialTrace"] traces out the subsystems in the list order from left to right; therefore, by convention, the list of subsystem indices should be given in descending order.
ResourceFunction["QuantumPartialTrace"], when applied to a QuantumDiscreteState, QuantumDiscreteOperator, QuantumMeasurementOperator, QuantumHamiltonianOperator or QuantumCircuitOperator object, will compute the ResourceFunction["QuantumPartialTrace"] of their associated QuantumBasis objects implicitly.
ResourceFunction["QuantumPartialTrace"][,{}] simply returns its first argument (or its operator form, in the case of circuits) without modification.

Examples

Basic Examples (1) 

Partially trace out qubits 5, 3 and 1 from a five-qubit Pauli-X QuantumBasis object to obtain a two-qubit QuantumBasis object:

In[1]:=
basis = ResourceFunction["QuantumBasis"]["PauliY", 5];
basis["BasisElementNames"]
Out[1]=
In[2]:=
newBasis = ResourceFunction["QuantumPartialTrace"][basis, {5, 3, 1}]
Out[2]=
In[3]:=
newBasis["BasisElementAssociation"]
Out[3]=

Scope (7) 

Partially trace out qubits 3 and 2 from a three-qubit pure QuantumDiscreteState object to obtain a single-qubit pure QuantumDiscreteState object:

In[4]:=
state = ResourceFunction["QuantumDiscreteState"][{1/2 + I/2, 0, 0, 1/2 + I/2, 1/2 - I/2, 0, 0, 1/2 - I/2}];
state["Amplitudes"]
Out[4]=
In[5]:=
newState = ResourceFunction["QuantumPartialTrace"][state, {3, 2}];
newState["Amplitudes"]
Out[5]=
In[6]:=
newState["PureStateQ"]
Out[6]=

On the other hand, if we partially trace out qubits 3 and 1 instead, then we obtain a single-qubit mixed QuantumDiscreteState object:

In[7]:=
newState2 = ResourceFunction["QuantumPartialTrace"][state, {3, 1}];
newState2["Amplitudes"]
Out[7]=
In[8]:=
newState2["MixedStateQ"]
Out[8]=
In[9]:=
newState2["Purity"]
Out[9]=

Partially trace out qubit 2 from a two-qubit mixed QuantumDiscreteState object to obtain a single-qubit mixed QuantumDiscreteState object:

In[10]:=
state2 = ResourceFunction[
    "QuantumDiscreteState"][{{1/8 + I/2, 1/2 - I/8, 1/4, -I/4}, {-1/2 + I/8, 1/8 + I/2, I/4, 1/4}, {1/4, -I/4, 3/8 - I/2, -1/2 - 3 I/8}, {I/4, 1/4, 1/2 + 3 I/8, 3/8 - I/2}}];
state2["Amplitudes"]
Out[10]=
In[11]:=
newState3 = ResourceFunction["QuantumPartialTrace"][state2, {2}];
newState3["Amplitudes"]
Out[11]=
In[12]:=
newState3["MixedStateQ"]
Out[12]=

On the other hand, if we partially trace out qubit 1 instead, then we obtain a single-qubit pure QuantumDiscreteState object:

In[13]:=
newState4 = ResourceFunction["QuantumPartialTrace"][state2, {1}];
newState4["Amplitudes"]
Out[13]=
In[14]:=
newState4["PureStateQ"]
Out[14]=

Partially trace out qubit 1 from an arity-3 QuantumDiscreteOperator object to obtain an arity-2 QuantumDiscreteOperator object:

In[15]:=
operator = ResourceFunction[
    "QuantumDiscreteOperator"][{{1/Sqrt[2], 1/Sqrt[2], 0, 0, 0, 0, 0, 0}, {1/Sqrt[2], -1/Sqrt[2], 0, 0, 0, 0, 0, 0}, {0, 0, 1/Sqrt[2], 1/Sqrt[2], 0, 0, 0, 0}, {0, 0, 1/Sqrt[2], -1/Sqrt[2], 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 1/Sqrt[2], 1/Sqrt[2]}, {0, 0, 0, 0, 0, 0, 1/Sqrt[2], -1/Sqrt[2]}, {0, 0, 0, 0, 1/Sqrt[2], 1/Sqrt[2], 0, 0}, {0, 0, 0, 0, 1/Sqrt[2], -1/Sqrt[2], 0, 0}}];
operator["MatrixRepresentation"]
Out[15]=
In[16]:=
newOperator = ResourceFunction["QuantumPartialTrace"][operator, {1}];
newOperator["Operator"]
Out[16]=
In[17]:=
newOperator["Order"]
Out[17]=

Partially trace out qubits 2 and 1 instead, to obtain an arity-1 QuantumDiscreteOperator object:

In[18]:=
newOperator2 = ResourceFunction["QuantumPartialTrace"][operator, {2, 1}];
newOperator2["Operator"]
Out[18]=
In[19]:=
newOperator2["Order"]
Out[19]=

Partially trace out qubit 4 from an arity-4 projection-valued QuantumMeasurementOperator object to obtain an arity-3 QuantumMeasurementOperator object:

In[20]:=
measurement = ResourceFunction[
    "QuantumMeasurementOperator"][{{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 3/2, -1/2, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, -1/2, 3/2, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, -1, 0, 3/2, -1/2, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, -1, -1/2, 3/2, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 3, -1, -2,
      0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, -1, 3, 0, -2, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, -2, 0, 3, -1, 0, 0, 0, 0}, {0, 0, 0,
      0, 0, 0, 0, 0, 0, -2, -1, 3, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9/2, -3/2, -3, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -3/2, 9/2, 0, -3}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -3,
      0, 9/2, -3/2}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -3, -3/2,
      9/2}}];
measurement["MatrixRepresentation"]
Out[20]=
In[21]:=
newMeasurement = ResourceFunction["QuantumPartialTrace"][measurement, {4}];
newMeasurement["MatrixRepresentation"]
Out[21]=
In[22]:=
newMeasurement["Order"]
Out[22]=

Partially trace out qubits 3 and 2 instead, to obtain an arity-2 QuantumMeasurementOperator object:

In[23]:=
newMeasurement2 = ResourceFunction["QuantumPartialTrace"][measurement, {3, 2}];
newMeasurement2["Operator"]
Out[23]=
In[24]:=
newMeasurement2["Order"]
Out[24]=

Partially trace out qubit 2 from an arity-2 positive operator-valued QuantumMeasurementOperator object to obtain an arity-1 positive operator-valued QuantumMeasurementOperator object:

In[25]:=
measurement2 = ResourceFunction[
    "QuantumMeasurementOperator"][{{{0, 0, 0, 0}, {0, 0, 0, 0}, {0, 0,
       1, -1}, {0, 0, -1, 1}}, {{0, 1, 0, -1}, {1, 0, -1, 0}, {0, -1, 0, 1}, {-1, 0, 1, 0}}, {{0, 0, -1, 1}, {0, 0, 1, -1}, {0, 0, 0, 0}, {0, 0, 0, 0}}, {{-1, 0, 1, 0}, {0, -1, 0, 1}, {1, 0, -1, 0}, {0, 1, 0, -1}}}, 2];
measurement2["Operator"]
Out[25]=
In[26]:=
newMeasurement3 = ResourceFunction["QuantumPartialTrace"][measurement2, {2}];
newMeasurement3["Operator"]
Out[26]=

Partially trace out qubit 1 instead:

In[27]:=
newMeasurement4 = ResourceFunction["QuantumPartialTrace"][measurement2, {1}];
newMeasurement4["Operator"]
Out[27]=

Partially trace out qubit 1 from an arity-2 QuantumHamiltonianOperator object to obtain an arity-1 QuantumHamiltonianOperator object:

In[28]:=
hamiltonian = ResourceFunction[
    "QuantumHamiltonianOperator"][{{1 + \[FormalT]^2, 0, 1 - \[FormalT]^2, 0}, {0, -1 - \[FormalT]^2, 0, -1 - \[FormalT]^2}, {1 - \[FormalT]^2, 0, 1 + \[FormalT]^2, 0}, {0, -1 - \[FormalT]^2, 0, -1 - \[FormalT]^2}}];
hamiltonian["Operator"]
Out[28]=
In[29]:=
newHamiltonian = ResourceFunction["QuantumPartialTrace"][hamiltonian, {1}];
newHamiltonian["Operator"]
Out[29]=

Partially trace out qubit 2 instead:

In[30]:=
newHamiltonian2 = ResourceFunction["QuantumPartialTrace"][hamiltonian, {2}];
newHamiltonian2["Operator"]
Out[30]=

Partially trace out qubit 3 from an arity-3 QuantumCircuitOperator object to obtain an arity-2 QuantumDiscreteOperator object:

In[31]:=
circuit = ResourceFunction[
    "QuantumCircuitOperator"][{ResourceFunction[
      "QuantumDiscreteOperator"]["CNOT", {2, 3}], ResourceFunction["QuantumDiscreteOperator"]["SWAP", {1, 3}], ResourceFunction["QuantumDiscreteOperator"][
     "Fourier", {1, 2, 3}]}];
circuit["MatrixRepresentation"] // MatrixForm
Out[31]=
In[32]:=
operator = ResourceFunction["QuantumPartialTrace"][circuit, {3}]
Out[32]=
In[33]:=
operator["Operator"]
Out[33]=

Partially trace out qubits 3 and 1 instead, to obtain an arity-1 QuantumDiscreteOperator object:

In[34]:=
operator2 = ResourceFunction["QuantumPartialTrace"][circuit, {3, 1}]
Out[34]=
In[35]:=
operator2["Operator"]
Out[35]=

Partially trace over higher-dimensional quantum objects:

In[36]:=
state = ResourceFunction["QuantumDiscreteState"][{1/3 Sqrt[5], I/Sqrt[15], (-I + Sqrt[2/3])/Sqrt[15], (1/3 + I/3)/
     Sqrt[5], -(1 - I)/
     Sqrt[15], (1 + I) (-I + Sqrt[2/3])/Sqrt[15], (1/3 - I/3)/
     Sqrt[5], (1 + I)/Sqrt[15], (1 - I) (-I + Sqrt[2/3])/Sqrt[15]}, 3];
state["Amplitudes"]
Out[36]=
In[37]:=
newState = ResourceFunction["QuantumPartialTrace"][state, {2}];
newState["Amplitudes"]
Out[37]=
In[38]:=
newState["Dimensions"]
Out[38]=

When taking the partial trace of a QuantumDiscreteState, QuantumDiscreteOperator, QuantumMeasurementOperator, QuantumHamiltonianOperator or QuantumCircuitOperator object, QuantumPartialTrace will also compute the partial trace of the associated QuantumBasis objects implicitly:

In[39]:=
state = ResourceFunction["QuantumDiscreteState"][{1/2 + I/2, 1/2 + I/2, 1/2 - I/2, 1/2 - I/2}, ResourceFunction["QuantumBasis"]["PauliY", 2]];
state["Amplitudes"]
Out[39]=
In[40]:=
newState = ResourceFunction["QuantumPartialTrace"][state, {2}];
newState["Amplitudes"]
Out[40]=
In[41]:=
newState["Basis"]
Out[41]=

The resulting basis is equivalent to partially tracing over the original basis:

In[42]:=
ResourceFunction["QuantumPartialTrace"][
 ResourceFunction["QuantumBasis"]["PauliY", 2], {2}]
Out[42]=

Publisher

Jonathan Gorard

Version History

  • 1.0.0 – 02 June 2021

Related Resources

License Information