コード例 #1
0
ファイル: consistent_phase_by.py プロジェクト: yijingS/Cirq
def assert_phase_by_is_consistent_with_unitary(val: Any):
    """Uses `val._unitary_` to check `val._phase_by_`'s behavior."""

    original = protocols.unitary(val, None)
    if original is None:
        # If there's no unitary, it's vacuously consistent.
        return
    qubit_count = len(original).bit_length() - 1
    original = original.reshape((2, 2) * qubit_count)

    for t in [0.125, -0.25, 1]:
        p = 1j**(t * 4)
        for i in range(qubit_count):
            phased = protocols.phase_by(val, t, i, default=None)
            if phased is None:
                # If not phaseable, then phase_by is vacuously consistent.
                continue

            actual = protocols.unitary(phased).reshape((2, 2) * qubit_count)

            expected = np.array(original)
            s = linalg.slice_for_qubits_equal_to([i], 1)
            expected[s] *= p
            s = linalg.slice_for_qubits_equal_to([qubit_count + i], 1)
            expected[s] *= np.conj(p)

            lin_alg_utils.assert_allclose_up_to_global_phase(
                actual,
                expected,
                atol=1e-8,
                err_msg='Phased unitary was incorrect for index #{}'.format(i))
コード例 #2
0
def assert_phase_by_is_consistent_with_unitary(val: Any):
    """Uses `val._unitary_` to check `val._phase_by_`'s behavior."""

    original = protocols.unitary(val, None)
    if original is None:
        # If there's no unitary, it's vacuously consistent.
        return
    qid_shape = protocols.qid_shape(val,
                                    default=(2,) *
                                    (len(original).bit_length() - 1))
    original = original.reshape(qid_shape * 2)

    for t in [0.125, -0.25, 1, sympy.Symbol('a'), sympy.Symbol('a') + 1]:
        p = 1j**(t*4)
        p = protocols.resolve_parameters(p, {'a': -0.125})
        for i in range(len(qid_shape)):
            phased = protocols.phase_by(val, t, i, default=None)
            if phased is None:
                # If not phaseable, then phase_by is vacuously consistent.
                continue

            phased = protocols.resolve_parameters(phased, {'a': -0.125})
            actual = protocols.unitary(phased).reshape(qid_shape * 2)

            expected = np.array(original)
            s = linalg.slice_for_qubits_equal_to([i], 1)
            expected[s] *= p
            s = linalg.slice_for_qubits_equal_to([len(qid_shape) + i], 1)
            expected[s] *= np.conj(p)

            lin_alg_utils.assert_allclose_up_to_global_phase(
                actual,
                expected,
                atol=1e-8,
                err_msg='Phased unitary was incorrect for index #{}'.format(i))
コード例 #3
0
def assert_phase_by_is_consistent_with_unitary(val: Any):
    """Uses `val._unitary_` to check `val._phase_by_`'s behavior."""

    original = protocols.unitary(val)
    qubit_count = len(original).bit_length() - 1
    original.shape = (2, 2) * qubit_count

    at_least_one_qubit_is_phaseable = False
    for t in [0.125, -0.25, 1]:
        p = 1j**(t * 4)
        for i in range(qubit_count):
            phased = protocols.phase_by(val, t, i, default=None)
            if phased is None:
                continue
            at_least_one_qubit_is_phaseable = True

            actual = protocols.unitary(phased)
            actual.shape = (2, 2) * qubit_count

            expected = np.array(original)
            s = linalg.slice_for_qubits_equal_to([i], 1)
            expected[s] *= p
            s = linalg.slice_for_qubits_equal_to([qubit_count + i], 1)
            expected[s] *= np.conj(p)

            lin_alg_utils.assert_allclose_up_to_global_phase(
                actual,
                expected,
                atol=1e-8,
                err_msg='Phased unitary was incorrect for index #{}'.format(i))

    assert at_least_one_qubit_is_phaseable, (
        '_phase_by_ is consistent with _unitary_, but only because the given '
        'value was not phaseable.')
コード例 #4
0
ファイル: gate_operation.py プロジェクト: nicklambourne/Cirq
 def _phase_by_(self, phase_turns: float,
                qubit_index: int) -> 'GateOperation':
     phased_gate = protocols.phase_by(self._gate, phase_turns, qubit_index,
                                      default=None)
     if phased_gate is None:
         return NotImplemented
     return GateOperation(phased_gate, self._qubits)
コード例 #5
0
ファイル: eject_z.py プロジェクト: sgangoly/Cirq
    def optimize_circuit(self, circuit: circuits.Circuit):
        # Tracks qubit phases (in half turns; multiply by pi to get radians).
        qubit_phase = defaultdict(lambda: 0)  # type: Dict[ops.QubitId, float]

        def dump_tracked_phase(qubits: Iterable[ops.QubitId],
                               index: int) -> None:
            """Zeroes qubit_phase entries by emitting Z gates."""
            for q in qubits:
                p = qubit_phase[q]
                if not decompositions.is_negligible_turn(p, self.tolerance):
                    dump_op = ops.Z(q)**(p * 2)
                    insertions.append((index, dump_op))
                qubit_phase[q] = 0

        deletions = []  # type: List[Tuple[int, ops.Operation]]
        inline_intos = []  # type: List[Tuple[int, ops.Operation]]
        insertions = []  # type: List[Tuple[int, ops.Operation]]
        for moment_index, moment in enumerate(circuit):
            for op in moment.operations:
                # Move Z gates into tracked qubit phases.
                h = _try_get_known_z_half_turns(op)
                if h is not None:
                    q = op.qubits[0]
                    qubit_phase[q] += h / 2
                    deletions.append((moment_index, op))
                    continue

                # Z gate before measurement is a no-op. Drop tracked phase.
                if ops.MeasurementGate.is_measurement(op):
                    for q in op.qubits:
                        qubit_phase[q] = 0

                # If there's no tracked phase, we can move on.
                phases = [qubit_phase[q] for q in op.qubits]
                if all(
                        decompositions.is_negligible_turn(p, self.tolerance)
                        for p in phases):
                    continue

                # Try to move the tracked phasing over the operation.
                phased_op = op
                for i, p in enumerate(phases):
                    if not decompositions.is_negligible_turn(
                            p, self.tolerance):
                        phased_op = protocols.phase_by(phased_op,
                                                       -p,
                                                       i,
                                                       default=None)
                if phased_op is not None:
                    deletions.append((moment_index, op))
                    inline_intos.append(
                        (moment_index, cast(ops.Operation, phased_op)))
                else:
                    dump_tracked_phase(op.qubits, moment_index)

        dump_tracked_phase(qubit_phase.keys(), len(circuit))
        circuit.batch_remove(deletions)
        circuit.batch_insert_into(inline_intos)
        circuit.batch_insert(insertions)
コード例 #6
0
 def _phase_by_(self, phase_turns: float, qubit_index: int):
     if qubit_index == 0:
         return self
     phased_gate = protocols.phase_by(self.sub_gate, phase_turns,
                                      qubit_index - 1, None)
     if phased_gate is None:
         return NotImplemented
     return ControlledGate(phased_gate)
コード例 #7
0
ファイル: eject_z.py プロジェクト: tkhan3/Cirq
    def optimize_circuit(self, circuit: circuits.Circuit):
        turns_state = defaultdict(lambda: 0)  # type: Dict[ops.QubitId, float]

        def dump_phases(qubits, index):
            for q in qubits:
                p = turns_state[q]
                if not is_negligible_turn(p, self.tolerance):
                    dump_op = ops.Z(q)**(p * 2)
                    insertions.append((index, dump_op))
                turns_state[q] = 0

        deletions = []  # type: List[Tuple[int, ops.Operation]]
        inline_intos = []  # type: List[Tuple[int, ops.Operation]]
        insertions = []  # type: List[Tuple[int, ops.Operation]]
        for moment_index, moment in enumerate(circuit):
            for op in moment.operations:
                h = _try_get_known_z_half_turns(op)
                if h is not None:
                    q = op.qubits[0]
                    turns_state[q] += h / 2
                    deletions.append((moment_index, op))
                    continue

                if ops.MeasurementGate.is_measurement(op):
                    for q in op.qubits:
                        turns_state[q] = 0

                phases = [turns_state[q] for q in op.qubits]
                if all(is_negligible_turn(p, self.tolerance) for p in phases):
                    continue

                phased_op = op
                for i, p in enumerate(phases):
                    if p and phased_op is not None:
                        phased_op = protocols.phase_by(phased_op,
                                                       -p,
                                                       i,
                                                       default=None)

                if phased_op is not None:
                    deletions.append((moment_index, op))
                    inline_intos.append(
                        (moment_index, cast(ops.Operation, phased_op)))
                else:
                    dump_phases(op.qubits, moment_index)

        dump_phases(turns_state.keys(), len(circuit))
        circuit.batch_remove(deletions)
        circuit.batch_insert_into(inline_intos)
        circuit.batch_insert(insertions)
コード例 #8
0
    def map_func(op: 'cirq.Operation', moment_index: int) -> 'cirq.OP_TREE':
        last_phased_xz_op.update({q: None for q in op.qubits})

        if tags_to_ignore & set(op.tags):
            # Op marked with no-compile, dump phases and do not cross.
            return [dump_tracked_phase(op.qubits), op]

        gate = op.gate
        # Return if circuit operation.
        if gate is None:
            return [dump_tracked_phase(op.qubits), op]

        # Swap phases if `op` is a swap operation.
        if _is_swaplike(gate):
            a, b = op.qubits
            qubit_phase[a], qubit_phase[b] = qubit_phase[b], qubit_phase[a]
            return op

        # Z gate before measurement is a no-op. Drop tracked phase.
        if isinstance(gate, ops.MeasurementGate):
            for q in op.qubits:
                qubit_phase[q] = 0
            return op

        # Move Z gates into tracked qubit phases.
        if isinstance(gate, ops.ZPowGate) and (
                eject_parameterized or not protocols.is_parameterized(gate)):
            qubit_phase[op.qubits[0]] += gate.exponent / 2
            return []

        # Try to move the tracked phases over the operation via protocols.phase_by(op)
        phased_op = op
        for i, p in enumerate([qubit_phase[q] for q in op.qubits]):
            if not single_qubit_decompositions.is_negligible_turn(p, atol):
                phased_op = protocols.phase_by(phased_op, -p, i, default=None)
        if phased_op is None:
            return [dump_tracked_phase(op.qubits), op]

        gate = phased_op.gate
        if isinstance(gate, ops.PhasedXZGate) and (
                eject_parameterized
                or not protocols.is_parameterized(gate.z_exponent)):
            qubit = phased_op.qubits[0]
            qubit_phase[qubit] += gate.z_exponent / 2
            gate = gate.with_z_exponent(0)
            phased_op = gate.on(qubit)
            phased_xz_replacements[moment_index, phased_op] = gate
            last_phased_xz_op[qubit] = (moment_index, phased_op)
        return phased_op
コード例 #9
0
 def _phase_by_(self, phase_turns: float, qubit_index: int) -> 'cirq.Operation':
     return protocols.phase_by(self.sub_operation, phase_turns, qubit_index)
コード例 #10
0
ファイル: eject_z.py プロジェクト: ybc1991/Cirq
    def optimize_circuit(self, circuit: circuits.Circuit):
        # Tracks qubit phases (in half turns; multiply by pi to get radians).
        qubit_phase: Dict[ops.Qid, float] = defaultdict(lambda: 0)
        deletions: List[Tuple[int, ops.Operation]] = []
        replacements: List[Tuple[int, ops.Operation, ops.Operation]] = []
        insertions: List[Tuple[int, ops.Operation]] = []
        phased_xz_replacements: Dict[Tuple[int, ops.Qid], int] = {}

        def dump_tracked_phase(qubits: Iterable[ops.Qid], index: int) -> None:
            """Zeroes qubit_phase entries by emitting Z gates."""
            for q in qubits:
                p = qubit_phase[q]
                qubit_phase[q] = 0
                if decompositions.is_negligible_turn(p, self.tolerance):
                    continue
                dumped = False
                moment_index = circuit.prev_moment_operating_on([q], index)
                if moment_index is not None:
                    op = circuit.moments[moment_index][q]
                    if op and isinstance(op.gate, ops.PhasedXZGate):
                        # Attach z-rotation to replacing PhasedXZ gate.
                        idx = phased_xz_replacements[moment_index, q]
                        _, _, repl_op = replacements[idx]
                        gate = cast(ops.PhasedXZGate, repl_op.gate)
                        repl_op = gate.with_z_exponent(p * 2).on(q)
                        replacements[idx] = (moment_index, op, repl_op)
                        dumped = True
                if not dumped:
                    # Add a new Z gate
                    dump_op = ops.Z(q)**(p * 2)
                    insertions.append((index, dump_op))

        for moment_index, moment in enumerate(circuit):
            for op in moment.operations:
                # Move Z gates into tracked qubit phases.
                h = _try_get_known_z_half_turns(op, self.eject_parameterized)
                if h is not None:
                    q = op.qubits[0]
                    qubit_phase[q] += h / 2
                    deletions.append((moment_index, op))
                    continue

                # Z gate before measurement is a no-op. Drop tracked phase.
                if isinstance(op.gate, ops.MeasurementGate):
                    for q in op.qubits:
                        qubit_phase[q] = 0

                # If there's no tracked phase, we can move on.
                phases = [qubit_phase[q] for q in op.qubits]
                if not isinstance(op.gate, ops.PhasedXZGate) and all(
                        decompositions.is_negligible_turn(p, self.tolerance)
                        for p in phases):
                    continue

                if _is_swaplike(op):
                    a, b = op.qubits
                    qubit_phase[a], qubit_phase[b] = qubit_phase[
                        b], qubit_phase[a]
                    continue

                # Try to move the tracked phasing over the operation.
                phased_op = op
                for i, p in enumerate(phases):
                    if not decompositions.is_negligible_turn(
                            p, self.tolerance):
                        phased_op = protocols.phase_by(phased_op,
                                                       -p,
                                                       i,
                                                       default=None)
                if phased_op is not None:
                    gate = phased_op.gate
                    if isinstance(gate, ops.PhasedXZGate) and (
                            self.eject_parameterized or
                            not protocols.is_parameterized(gate.z_exponent)):
                        qubit = phased_op.qubits[0]
                        qubit_phase[qubit] += gate.z_exponent / 2
                        phased_op = gate.with_z_exponent(0).on(qubit)
                        repl_idx = len(replacements)
                        phased_xz_replacements[moment_index, qubit] = repl_idx
                    replacements.append((moment_index, op, phased_op))
                else:
                    dump_tracked_phase(op.qubits, moment_index)

        dump_tracked_phase(qubit_phase.keys(), len(circuit))
        circuit.batch_remove(deletions)
        circuit.batch_replace(replacements)
        circuit.batch_insert(insertions)