-
Notifications
You must be signed in to change notification settings - Fork 269
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
d3631e2
commit 0d1a78f
Showing
6 changed files
with
237 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,57 @@ | ||
# Copyright 2018 ProjectQ-Framework (www.projectq.ch) | ||
# | ||
# Licensed under the Apache License, Version 2.0 (the "License"); | ||
# you may not use this file except in compliance with the License. | ||
# You may obtain a copy of the License at | ||
# | ||
# http://www.apache.org/licenses/LICENSE-2.0 | ||
# | ||
# Unless required by applicable law or agreed to in writing, software | ||
# distributed under the License is distributed on an "AS IS" BASIS, | ||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
# See the License for the specific language governing permissions and | ||
# limitations under the License. | ||
|
||
from ._basics import BasicGate | ||
|
||
|
||
class StatePreparation(BasicGate): | ||
""" | ||
Gate for transforming qubits in state |0> to any desired quantum state. | ||
""" | ||
def __init__(self, final_state): | ||
""" | ||
Initialize StatePreparation gate. | ||
Example: | ||
.. code-block:: python | ||
qureg = eng.allocate_qureg(2) | ||
StatePreparation([0.5, -0.5j, -0.5, 0.5]) | qureg | ||
Note: | ||
The amplitude of state k is final_state[k]. When the state k is | ||
written in binary notation, then qureg[0] denotes the qubit | ||
whose state corresponds to the least significant bit of k. | ||
Args: | ||
final_state(list[complex]): wavefunction of the desired | ||
quantum state. len(final_state) must | ||
be 2**len(qureg). Must be normalized! | ||
""" | ||
BasicGate.__init__(self) | ||
self.final_state = list(final_state) | ||
|
||
def __str__(self): | ||
return "StatePreparation" | ||
|
||
def __eq__(self, other): | ||
if isinstance(other, self.__class__): | ||
return self.final_state == other.final_state | ||
return False | ||
|
||
def __ne__(self, other): | ||
return not self.__eq__(other) | ||
|
||
def __hash__(self): | ||
return hash("StatePreparation(" + str(self.final_state) + ")") |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
# Copyright 2018 ProjectQ-Framework (www.projectq.ch) | ||
# | ||
# Licensed under the Apache License, Version 2.0 (the "License"); | ||
# you may not use this file except in compliance with the License. | ||
# You may obtain a copy of the License at | ||
# | ||
# http://www.apache.org/licenses/LICENSE-2.0 | ||
# | ||
# Unless required by applicable law or agreed to in writing, software | ||
# distributed under the License is distributed on an "AS IS" BASIS, | ||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
# See the License for the specific language governing permissions and | ||
# limitations under the License. | ||
|
||
"""Tests for projectq.ops._state_prep.""" | ||
|
||
import projectq | ||
|
||
from projectq.ops import _state_prep, X | ||
|
||
|
||
def test_equality_and_hash(): | ||
gate1 = _state_prep.StatePreparation([0.5, -0.5, 0.5, -0.5]) | ||
gate2 = _state_prep.StatePreparation([0.5, -0.5, 0.5, -0.5]) | ||
gate3 = _state_prep.StatePreparation([0.5, -0.5, 0.5, 0.5]) | ||
assert gate1 == gate2 | ||
assert hash(gate1) == hash(gate2) | ||
assert gate1 != gate3 | ||
assert gate1 != X | ||
|
||
|
||
def test_str(): | ||
gate1 = _state_prep.StatePreparation([0, 1]) | ||
assert str(gate1) == "StatePreparation" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,79 @@ | ||
# Copyright 2018 ProjectQ-Framework (www.projectq.ch) | ||
# | ||
# Licensed under the Apache License, Version 2.0 (the "License"); | ||
# you may not use this file except in compliance with the License. | ||
# You may obtain a copy of the License at | ||
# | ||
# http://www.apache.org/licenses/LICENSE-2.0 | ||
# | ||
# Unless required by applicable law or agreed to in writing, software | ||
# distributed under the License is distributed on an "AS IS" BASIS, | ||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
# See the License for the specific language governing permissions and | ||
# limitations under the License. | ||
|
||
""" | ||
Registers decomposition for StatePreparation. | ||
""" | ||
|
||
import cmath | ||
import math | ||
|
||
from projectq.cengines import DecompositionRule | ||
from projectq.meta import Control, Dagger | ||
from projectq.ops import (StatePreparation, Ry, Rz, UniformlyControlledRy, | ||
UniformlyControlledRz, Ph) | ||
|
||
|
||
def _decompose_state_preparation(cmd): | ||
""" | ||
Implements state preparation based on arXiv:quant-ph/0407010v1. | ||
""" | ||
eng = cmd.engine | ||
assert len(cmd.qubits) == 1 | ||
num_qubits = len(cmd.qubits[0]) | ||
qureg = cmd.qubits[0] | ||
final_state = cmd.gate.final_state | ||
if len(final_state) != 2**num_qubits: | ||
raise ValueError("Length of final_state is invalid.") | ||
with Control(eng, cmd.control_qubits): | ||
# As in the paper reference, we implement the inverse: | ||
with Dagger(eng): | ||
# Cancel all the relative phases | ||
phase_of_blocks = [] | ||
for amplitude in final_state: | ||
phase_of_blocks.append(cmath.phase(amplitude)) | ||
for target_qubit in range(len(qureg)): | ||
angles = [] | ||
phase_of_next_blocks = [] | ||
for block in range(2**(len(qureg)-target_qubit-1)): | ||
phase0 = phase_of_blocks[2*block] | ||
phase1 = phase_of_blocks[2*block+1] | ||
angles.append(phase0 - phase1) | ||
phase_of_next_blocks.append((phase0 + phase1)/2.) | ||
UniformlyControlledRz(angles) | (qureg[(target_qubit+1):], | ||
qureg[target_qubit]) | ||
phase_of_blocks = phase_of_next_blocks | ||
# Cancel global phase | ||
Ph(-phase_of_blocks[0]) | qureg[-1] | ||
# Remove amplitudes from states which contain a bit value 1: | ||
abs_of_blocks = [] | ||
for amplitude in final_state: | ||
abs_of_blocks.append(abs(amplitude)) | ||
for target_qubit in range(len(qureg)): | ||
angles = [] | ||
abs_of_next_blocks = [] | ||
for block in range(2**(len(qureg)-target_qubit-1)): | ||
a0 = abs_of_blocks[2*block] | ||
a1 = abs_of_blocks[2*block+1] | ||
angles.append(-2. * math.acos(a0/math.sqrt(a0**2 + a1**2))) | ||
abs_of_next_blocks.append(math.sqrt(a0**2 + a1**2)) | ||
UniformlyControlledRy(angles) | (qureg[(target_qubit+1):], | ||
qureg[target_qubit]) | ||
abs_of_blocks = abs_of_next_blocks | ||
|
||
|
||
#: Decomposition rules | ||
all_defined_decomposition_rules = [ | ||
DecompositionRule(StatePreparation, _decompose_state_preparation) | ||
] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,64 @@ | ||
# Copyright 2018 ProjectQ-Framework (www.projectq.ch) | ||
# | ||
# Licensed under the Apache License, Version 2.0 (the "License"); | ||
# you may not use this file except in compliance with the License. | ||
# You may obtain a copy of the License at | ||
# | ||
# http://www.apache.org/licenses/LICENSE-2.0 | ||
# | ||
# Unless required by applicable law or agreed to in writing, software | ||
# distributed under the License is distributed on an "AS IS" BASIS, | ||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
# See the License for the specific language governing permissions and | ||
# limitations under the License. | ||
|
||
"""Tests for projectq.setups.decompositions.stateprep2cnot.""" | ||
|
||
import cmath | ||
from copy import deepcopy | ||
import math | ||
|
||
import numpy as np | ||
import pytest | ||
|
||
import projectq | ||
from projectq.ops import All, Command, Measure, Ry, Rz, StatePreparation, Ph | ||
from projectq.setups import restrictedgateset | ||
from projectq.types import WeakQubitRef | ||
|
||
import projectq.setups.decompositions.stateprep2cnot as stateprep2cnot | ||
|
||
|
||
def test_wrong_final_state(): | ||
qb0 = WeakQubitRef(engine=None, idx=0) | ||
qb1 = WeakQubitRef(engine=None, idx=1) | ||
cmd = Command(None, StatePreparation([0, 1j]), qubits=([qb0, qb1],)) | ||
with pytest.raises(ValueError): | ||
stateprep2cnot._decompose_state_preparation(cmd) | ||
|
||
|
||
@pytest.mark.parametrize("n_qubits", [1, 2, 3, 4]) | ||
def test_state_preparation(n_qubits): | ||
engine_list = restrictedgateset.get_engine_list( | ||
one_qubit_gates=(Ry, Rz, Ph)) | ||
eng = projectq.MainEngine(engine_list=engine_list) | ||
qureg = eng.allocate_qureg(n_qubits) | ||
eng.flush() | ||
|
||
f_state = [0.2+0.1*x*cmath.exp(0.1j+0.2j*x) for x in range(2**n_qubits)] | ||
norm = 0 | ||
for amplitude in f_state: | ||
norm += abs(amplitude)**2 | ||
f_state = [x / math.sqrt(norm) for x in f_state] | ||
|
||
StatePreparation(f_state) | qureg | ||
eng.flush() | ||
|
||
wavefunction = deepcopy(eng.backend.cheat()[1]) | ||
# Test that simulator hasn't reordered wavefunction | ||
mapping = eng.backend.cheat()[0] | ||
for key in mapping: | ||
assert mapping[key] == key | ||
All(Measure) | qureg | ||
eng.flush() | ||
assert np.allclose(wavefunction, f_state, rtol=1e-10, atol=1e-10) |