Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
ca3b8d5
First version of exporting to open qasm
clausia Nov 23, 2020
9c31e79
Optional third party libraries
clausia Nov 23, 2020
660f53b
generators
georgios-ts Dec 8, 2020
bc37fb5
Merge remote-tracking branch 'upstream/devel' into generators
georgios-ts Dec 8, 2020
721e889
exclude rotations
georgios-ts Dec 9, 2020
fea8e89
refactor Compiler
georgios-ts Dec 12, 2020
145e796
Import/export OpenQASM code and import/export to pyzx package for ZX-…
clausia Jan 2, 2021
733a26b
Merge branch 'devel' into add-pyzx-and-qasm
clausia Jan 4, 2021
85cd14d
improve comment
clausia Jan 6, 2021
058e6f6
Better equivalences for CH and Y that includes the power parameter
clausia Jan 8, 2021
45296ce
fix comments in compiler.py
clausia Jan 8, 2021
15d0841
dd matrix representation of U gate
clausia Jan 8, 2021
290ced0
More tests for gates u1,u2,u3,U
clausia Jan 8, 2021
7009185
Improve qubits property in QGateImpl
clausia Jan 11, 2021
23b8ab7
correct gates equivalent to CH
clausia Jan 12, 2021
28f069b
Tests for import/export OpenQASM code
clausia Jan 13, 2021
66626fd
Correct order for U gate equivalent circuit and improvement in tests …
clausia Jan 14, 2021
d178f26
Error (and fix) because changes in _gates_impl.py regarding _qubits a…
clausia Jan 14, 2021
0c55263
Tests for import/export OpenQASM code
clausia Jan 14, 2021
4d14b97
Remove temporal comment
clausia Jan 14, 2021
99d10b4
Avoid some warnings
clausia Jan 14, 2021
9aa17b3
Tests for convert from/to pyzx
clausia Jan 15, 2021
599777c
Test if a circuit reduced within pyzx remains the same when returned …
clausia Jan 15, 2021
ff68b80
Skip pyzx tests if pyzx package is not installed
clausia Jan 15, 2021
7b41f99
Improve tests for new compile functions (ry, y, ch)
clausia Jan 15, 2021
344c22c
Merge branch 'devel' into add-pyzx-and-qasm
clausia Jan 15, 2021
a8f4769
Variables are not needed when importing OpqnQASM code
clausia Jan 15, 2021
209ddf1
Merge branch 'devel' into add-pyzx-and-qasm
clausia Jan 20, 2021
eb89bac
minor fixes
georgios-ts Jan 20, 2021
ecaab9c
Merge remote-tracking branch 'upstream/devel' into compiler
georgios-ts Jan 20, 2021
dba16d8
fix syntax error
georgios-ts Jan 20, 2021
6022cbc
Merge branch 'merge-with-georgios' into compiler
clausia Jan 21, 2021
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -16,3 +16,6 @@ qulacs # default simulator, remove if the installation gives you trouble
#pyquil # you need to install the forest-sdk
#qulacs-gpu
#qibo <= 0.1.1

#optional third party libraries
#pyzx
2 changes: 2 additions & 0 deletions src/tequila/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@
INSTALLED_SAMPLERS, \
INSTALLED_SIMULATORS, SUPPORTED_BACKENDS, INSTALLED_BACKENDS, show_available_simulators
from tequila.wavefunction import QubitWaveFunction
from tequila.circuit.qasm import export_open_qasm, import_open_qasm, import_open_qasm_from_file
from tequila.circuit.pyzx import convert_to_pyzx, convert_from_pyzx
import tequila.quantumchemistry as chemistry # shortcut
from tequila.quantumchemistry import Molecule, MoleculeFromOpenFermion

Expand Down
79 changes: 57 additions & 22 deletions src/tequila/circuit/_gates_impl.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,9 @@
from abc import ABC
from tequila import TequilaException
from tequila.objective.objective import Variable, FixedVariable, assign_variable,Objective,VectorObjective
from tequila.hamiltonian import PauliString, QubitHamiltonian
from tequila.hamiltonian import PauliString, QubitHamiltonian, paulis
from tequila.tools import list_assignment
from numpy import pi

from dataclasses import dataclass

Expand All @@ -30,30 +31,35 @@ def control(self):

@property
def qubits(self):
return self._qubits
# Set the active qubits
if self.control:
qubits = self.target + self.control
else:
qubits = self.target
return sorted(tuple(set(qubits)))

@property
def max_qubit(self):
return self._max_qubit
return self.compute_max_qubit()

def extract_variables(self):
return []

def is_parametrized(self) -> bool:
return hasattr(self, "parameter")

def __init__(self, name, target: UnionList, control: UnionList = None):
def make_generator(self, include_controls=False):
if self.generator and include_controls and self.is_controlled():
return paulis.Qm(self.control) * self.generator

return self.generator

def __init__(self, name, target: UnionList, control: UnionList = None, generator: QubitHamiltonian = None):
self._name = name
self._target = tuple(list_assignment(target))
self._control = tuple(list_assignment(control))
self.finalize()
# Set the active qubits
if self.control:
self._qubits = self.target + self.control
else:
self._qubits = self.target
self._qubits = sorted(tuple(set(self._qubits)))
self._max_qubit = self.compute_max_qubit()
self.generator = generator

def copy(self):
return copy.deepcopy(self)
Expand Down Expand Up @@ -89,7 +95,7 @@ def finalize(self):
for c in self.target:
if c in self.control:
raise Exception("control and target are the same qubit: " + self.__str__())
if hasattr(self,"generator"):
if hasattr(self,"generator") and self.generator:
if set(list(self.generator.qubits)) != set(list(self.target)):
raise Exception("qubits of generator and targets don't agree -- mapping error?\n gate = {}".format(self.__str__()))
if hasattr(self, "generators"):
Expand Down Expand Up @@ -134,13 +140,9 @@ def __eq__(self, other):
def map_qubits(self, qubit_map: dict):
mapped = copy.deepcopy(self)
mapped._target = tuple([qubit_map[i] for i in self.target])
qubits = mapped._target
if self.control is not None:
mapped._control = tuple([qubit_map[i] for i in self.control])
qubits += mapped._control
mapped._qubits = sorted(tuple(set(qubits)))
mapped._max_qubit = mapped.compute_max_qubit()
if hasattr(self, "generator"):
if hasattr(self, "generator") and self.generator:
mapped.generator = self.generator.map_qubits(qubit_map=qubit_map)
if hasattr(self, "generators"):
mapped.generators = [i.map_qubits(qubit_map=qubit_map) for i in self.generators]
Expand Down Expand Up @@ -169,8 +171,9 @@ def parameter(self):
def parameter(self, other):
self.parameter = assign_variable(variable=other)

def __init__(self, name, parameter: UnionParam, target: UnionList, control: UnionList = None):
super().__init__(name=name, target=target, control=control)
def __init__(self, name, parameter: UnionParam, target: UnionList, control: UnionList = None,
generator: QubitHamiltonian = None):
super().__init__(name=name, target=target, control=control, generator=generator)
if isinstance(parameter, VectorObjective):
raise TequilaException('Received VectorObjective {} as parameter. This is forbidden.'.format(parameter))
self._parameter = assign_variable(variable=parameter)
Expand Down Expand Up @@ -233,6 +236,7 @@ def __init__(self, axis, angle, target: list, control: list = None):
assert (angle is not None)
super().__init__(eigenvalues_magnitude=0.5, name=self.get_name(axis=axis), parameter=angle, target=target, control=control)
self._axis = self.assign_axis(axis)
self.generator = self.assign_generator(self.axis, self.target)

@staticmethod
def assign_axis(axis):
Expand All @@ -244,6 +248,15 @@ def assign_axis(axis):
assert (axis in [0, 1, 2])
return axis

@staticmethod
def assign_generator(axis, qubits):
if axis == 0:
return sum(paulis.X(q) for q in qubits)
if axis == 1:
return sum(paulis.Y(q) for q in qubits)

return sum(paulis.Z(q) for q in qubits)

def dagger(self):
result = copy.deepcopy(self)
result._parameter = assign_variable(-self.parameter)
Expand All @@ -255,6 +268,7 @@ class PhaseGateImpl(DifferentiableGateImpl):
def __init__(self, phase, target: list, control: list = None):
assert (phase is not None)
super().__init__(eigenvalues_magnitude=0.5, name='Phase', parameter=phase, target=target, control=control)
self.generator = paulis.Z(target) - paulis.I(target)

def dagger(self):
result = copy.deepcopy(self)
Expand All @@ -268,14 +282,35 @@ def __pow__(self, power, modulo=None):


class PowerGateImpl(ParametrizedGateImpl):
"""
Attributes
---------
power
numeric type (fixed exponent) or hashable type (parametrized exponent)
parameter
power multiplied by pi
to be consitent with exp(-i a/2 G) representation [a: gate.parameter, G: gate.generator]
"""

Comment thread
georgios-ts marked this conversation as resolved.
@property
def power(self):
return self._power

@power.setter
def power(self, other):
self._power = assign_variable(variable=other)

def __init__(self, name, target: list, power=None, control: list = None):
super().__init__(name=name, parameter=power, target=target, control=control)
def __init__(self, name, target: list, power, control: list = None, generator: QubitHamiltonian = None):
super().__init__(name=name, parameter=power * pi, target=target, control=control, generator=generator)
self._power = assign_variable(variable=power)

def dagger(self):
result = copy.deepcopy(self)
result._parameter = assign_variable(-self.parameter)
result._power = assign_variable(-self.power)
return result


class GeneralizedRotationImpl(DifferentiableGateImpl):
"""
A gate which behaves like a generalized rotation
Expand Down Expand Up @@ -321,6 +356,7 @@ def dagger(self):
def __init__(self, paulistring: PauliString, angle: float, control: typing.List[int] = None):
super().__init__(eigenvalues_magnitude=0.5, name="Exp-Pauli", target=tuple(t for t in paulistring.keys()), control=control, parameter=angle)
self.paulistring = paulistring
self.generator = QubitHamiltonian.from_paulistrings(paulistring)
self.finalize()

def __str__(self):
Expand Down Expand Up @@ -420,4 +456,3 @@ def dagger(self):
angles.append(-angle)
result.angles = angles
return result

Loading