Example #1
0
    def _base_iterator(self, circuit, qubit_order, initial_state,
                       perform_measurements=True):
        qubits = cirq.QubitOrder.as_qubit_order(qubit_order).order_for(
            circuit.all_qubits())
        num_qubits = len(qubits)
        qid_shape = cirq.qid_shape(qubits)
        qubit_map = {q: i for i, q in enumerate(qubits)}
        if isinstance(initial_state, int):
            state_val = initial_state
        else:
            state_val = cirq.big_endian_digits_to_int(initial_state,
                                                      base=qid_shape)
        state = _State.from_basis_state(state_val,
                                        qid_shape,
                                        path_limit=self.path_limit,
                                        tolerance=self.tolerance)
        if len(circuit) == 0:
            yield FeynmanPathSimulatorStep(state, {}, qubit_map)

        def on_stuck(bad_op):
            return TypeError(
                "Can't simulate unknown operations that don't specify a"
                "unitary or a decomposition. {!r}".format(bad_op))

        def keep(potential_op):
            return (cirq.has_unitary(potential_op) or
                    cirq.has_mixture(potential_op) or
                    cirq.is_measurement(potential_op) or
                    cirq.op_gate_isinstance(potential_op, cirq.ResetChannel))

        def simulate_op(op, temp_state):
            indices = [qubit_map[q] for q in op.qubits]
            if cirq.op_gate_isinstance(op, cirq.ResetChannel):
                self._simulate_reset(op, cirq.ResetChannel)
            elif cirq.is_measurement(op):
                if perform_measurements:
                    self._simulate_measurement(
                        op, temp_state, indices, measurements)
            elif cirq.has_mixture(op):
                self._simulate_mixture(op, temp_state, indices)
            else:
                if cirq.num_qubits(op) <= 3:
                    self._simulate_unitary(op, temp_state, indices)
                else:
                    decomp_ops = cirq.decompose_once(op, default=None)
                    if decomp_ops is None:
                        self._simulate_unitary(op, temp_state, indices)
                    else:
                        for sub_op in cirq.flatten_op_tree(decomp_ops):
                            simulate_op(sub_op, temp_state)

        for moment in circuit:
            measurements = defaultdict(list)
            known_ops = cirq.decompose(moment, keep=keep,
                                       on_stuck_raise=on_stuck)
            for op in known_ops:
                simulate_op(op, state)
            yield FeynmanPathSimulatorStep(state, measurements, qubit_map)
Example #2
0
def test_big_endian_digits_to_int():
    with pytest.raises(ValueError, match=r'len\(base\)'):
        _ = cirq.big_endian_digits_to_int([1, 2, 3], base=[2, 3, 5, 7])
    with pytest.raises(ValueError, match='Out of range'):
        _ = cirq.big_endian_digits_to_int([105, 106, 107], base=4)

    assert cirq.big_endian_digits_to_int([0, 1], base=102) == 1
    assert cirq.big_endian_digits_to_int([1, 0], base=102) == 102
    assert cirq.big_endian_digits_to_int([1, 0], base=[5, 7]) == 7
    assert cirq.big_endian_digits_to_int([0, 1], base=[5, 7]) == 1
    assert cirq.big_endian_digits_to_int([1, 2, 3, 4], base=[2, 3, 5,
                                                             7]) == 200
    assert cirq.big_endian_digits_to_int([1, 2, 3, 4], base=10) == 1234

    # Use-once digit and base iterators.
    assert cirq.big_endian_digits_to_int((e for e in [1, 2, 3, 4]),
                                         base=(e for e in [2, 3, 5, 7])) == 200
Example #3
0
 def _apply_unitary(self, op, unitary, op_shape, state, indices):
     indices = list(indices)
     target_state = state[indices]
     target_val = cirq.big_endian_digits_to_int(target_state, base=op_shape)
     result_wavefunction = unitary[:, target_val]
     result_val = np.argmax(np.abs(result_wavefunction))
     if not (np.isclose(np.abs(result_wavefunction[result_val]), 1)
             and np.sum(1 - np.isclose(result_wavefunction, 0)) == 1):
         # The output state vector does not represent a single basis state
         raise ValueError(
             "Can't simulate non-classical operations. "
             "The operation's unitary is not a permutation matrix: "
             "{!r}\n{!r}".format(op, unitary))
     result_state = cirq.big_endian_int_to_digits(result_val, base=op_shape)
     state[indices] = result_state
Example #4
0
 def apply_unitary(self, indices, unitary):
     sub_shape = [self.qid_shape[i] for i in indices]
     self.buffer_state.clear()
     for digits, amplitude in self.state.items():
         new_digits = list(digits)
         if np.isclose(amplitude, 0, rtol=1, atol=self.tolerance):
             continue
         target_val = cirq.big_endian_digits_to_int(
             (digits[i] for i in indices), base=sub_shape)
         result_wavefunction = unitary[:, target_val]
         for result_amp, new_targ_digits in zip(
                 result_wavefunction,
                 itertools.product(*(range(d) for d in sub_shape))):
             if np.isclose(result_amp, 0, rtol=1, atol=self.tolerance):
                 continue
             for i, dig in zip(indices, new_targ_digits):
                 new_digits[i] = dig
             self.buffer_state[tuple(new_digits)] += amplitude * result_amp
     self.state, self.buffer_state = self.buffer_state, self.state
     if len(self.state) > self.path_limit:
         raise PathLimitError
Example #5
0
    def _base_iterator(self,
                       circuit,
                       qubit_order,
                       initial_state,
                       perform_measurements=True):
        qubits = cirq.QubitOrder.as_qubit_order(qubit_order).order_for(
            circuit.all_qubits())
        num_qubits = len(qubits)
        qid_shape = cirq.qid_shape(qubits)
        qubit_map = {q: i for i, q in enumerate(qubits)}
        if isinstance(initial_state, int):
            state_val = initial_state
        else:
            state_val = cirq.big_endian_digits_to_int(initial_state,
                                                      base=qid_shape)
        state = np.array(list(
            cirq.big_endian_int_to_digits(state_val, base=qid_shape)),
                         dtype=np.uint8)
        if len(circuit) == 0:
            yield ClassicalSimulatorStep(state, {}, qubit_map)

        def on_stuck(bad_op):
            return TypeError(
                "Can't simulate unknown operations that don't specify a "
                "unitary or a decomposition. {!r}".format(bad_op))

        def keep(op):
            return ((cirq.num_qubits(op) <= 32 and
                     (cirq.has_unitary(op) or cirq.has_mixture(op)))
                    or cirq.is_measurement(op)
                    or isinstance(op.gate, cirq.ResetChannel))

        def simulate_op(op, temp_state):
            indices = [qubit_map[q] for q in op.qubits]
            if isinstance(op.gate, cirq.ResetChannel):
                self._simulate_reset(op, temp_state, indices)
            elif cirq.is_measurement(op):
                if perform_measurements:
                    self._simulate_measurement(op, temp_state, indices,
                                               measurements)
            else:
                decomp_ops = cirq.decompose_once(op, default=None)
                if decomp_ops is None:
                    self._simulate_from_matrix(op, temp_state, indices)
                else:
                    try:
                        temp2_state = temp_state.copy()
                        for sub_op in cirq.flatten_op_tree(decomp_ops):
                            simulate_op(sub_op, temp2_state)
                        temp_state[...] = temp2_state
                    except ValueError:
                        # Non-classical unitary in the decomposition
                        self._simulate_from_matrix(op, temp_state, indices)

        for moment in circuit:
            measurements = defaultdict(list)
            known_ops = cirq.decompose(moment,
                                       keep=keep,
                                       on_stuck_raise=on_stuck)
            for op in known_ops:
                simulate_op(op, state)
            yield ClassicalSimulatorStep(state.copy(), measurements, qubit_map)