Esempio n. 1
0
def add_op_to_circuit(qsim_op: cirq.GateOperation, time: int,
                      qubit_to_index_dict: Dict[cirq.Qid, int],
                      circuit: Union[qsim.Circuit, qsim.NoisyCircuit]):
    """Adds an operation to a noisy or noiseless circuit."""
    qsim_gate = qsim_op.gate
    gate_kind = _cirq_gate_kind(qsim_gate)
    qubits = [qubit_to_index_dict[q] for q in qsim_op.qubits]

    qsim_qubits = qubits
    is_controlled = isinstance(qsim_gate, cirq.ops.ControlledGate)
    if is_controlled:
        control_qubits, control_values = _control_details(qsim_gate, qubits)
        if control_qubits is None:
            # This gate has no valid control, and will be omitted.
            return

        if qsim_gate.num_qubits() > 4:
            raise NotImplementedError(
                f'Received control gate on {gate.num_qubits()} target qubits; '
                + 'only up to 4-qubit gates are supported.')

        qsim_qubits = qubits[qsim_gate.num_controls():]
        qsim_gate = qsim_gate.sub_gate

    if (gate_kind == qsim.kTwoQubitDiagonalGate
            or gate_kind == qsim.kThreeQubitDiagonalGate):
        if isinstance(circuit, qsim.Circuit):
            qsim.add_diagonal_gate(time, qsim_qubits,
                                   qsim_gate._diag_angles_radians, circuit)
        else:
            qsim.add_diagonal_gate_channel(time, qsim_qubits,
                                           qsim_gate._diag_angles_radians,
                                           circuit)
    elif gate_kind == qsim.kMatrixGate:
        m = [
            val for i in list(cirq.unitary(qsim_gate).flat)
            for val in [i.real, i.imag]
        ]
        if isinstance(circuit, qsim.Circuit):
            qsim.add_matrix_gate(time, qsim_qubits, m, circuit)
        else:
            qsim.add_matrix_gate_channel(time, qsim_qubits, m, circuit)
    else:
        params = {
            p.strip('_'): val
            for p, val in vars(qsim_gate).items()
            if isinstance(val, float) or isinstance(val, int)
        }
        if isinstance(circuit, qsim.Circuit):
            qsim.add_gate(gate_kind, time, qsim_qubits, params, circuit)
        else:
            qsim.add_gate_channel(gate_kind, time, qsim_qubits, params,
                                  circuit)

    if is_controlled:
        if isinstance(circuit, qsim.Circuit):
            qsim.control_last_gate(control_qubits, control_values, circuit)
        else:
            qsim.control_last_gate_channel(control_qubits, control_values,
                                           circuit)
Esempio n. 2
0
    def translate_cirq_to_qsim(
        self,
        qubit_order: cirq.ops.QubitOrderOrList = cirq.ops.QubitOrder.DEFAULT
    ) -> qsim.Circuit:
        """
        Translates this Cirq circuit to the qsim representation.
        :qubit_order: Ordering of qubits
        :return: a C++ qsim Circuit object
        """

        qsim_circuit = qsim.Circuit()
        qsim_circuit.num_qubits = len(self.all_qubits())
        ordered_qubits = cirq.ops.QubitOrder.as_qubit_order(
            qubit_order).order_for(self.all_qubits())

        # qsim numbers qubits in reverse order from cirq
        ordered_qubits = list(reversed(ordered_qubits))

        qubit_to_index_dict = {q: i for i, q in enumerate(ordered_qubits)}
        time_offset = 0
        for moment in self:
            ops_by_gate = [
                cirq.decompose(op,
                               keep=lambda x: _cirq_gate_kind(x.gate) != None)
                for op in moment
            ]
            moment_length = max(len(gate_ops) for gate_ops in ops_by_gate)

            # Gates must be added in time order.
            for gi in range(moment_length):
                for gate_ops in ops_by_gate:
                    if gi >= len(gate_ops):
                        continue
                    qsim_op = gate_ops[gi]
                    gate_kind = _cirq_gate_kind(qsim_op.gate)
                    time = time_offset + gi
                    qubits = [qubit_to_index_dict[q] for q in qsim_op.qubits]
                    params = {
                        p.strip('_'): val
                        for p, val in vars(qsim_op.gate).items()
                        if isinstance(val, float) or isinstance(val, int)
                    }
                    if gate_kind == qsim.kMatrixGate1:
                        qsim.add_matrix1(time, qubits,
                                         cirq.unitary(qsim_op.gate).tolist(),
                                         qsim_circuit)
                    elif gate_kind == qsim.kMatrixGate2:
                        qsim.add_matrix2(time, qubits,
                                         cirq.unitary(qsim_op.gate).tolist(),
                                         qsim_circuit)
                    else:
                        qsim.add_gate(gate_kind, time, qubits, params,
                                      qsim_circuit)
            time_offset += moment_length

        return qsim_circuit
Esempio n. 3
0
  def translate_cirq_to_qsim(
      self,
      qubit_order: cirq.ops.QubitOrderOrList = cirq.ops.QubitOrder.DEFAULT
  ) -> qsim.Circuit:
    """
        Translates this Cirq circuit to the qsim representation.
        :qubit_order: Ordering of qubits
        :return: a C++ qsim Circuit object
        """

    qsim_circuit = qsim.Circuit()
    qsim_circuit.num_qubits = len(self.all_qubits())
    ordered_qubits = cirq.ops.QubitOrder.as_qubit_order(qubit_order).order_for(
        self.all_qubits())

    # qsim numbers qubits in reverse order from cirq
    ordered_qubits = list(reversed(ordered_qubits))

    def has_qsim_kind(op: cirq.ops.GateOperation):
      return _cirq_gate_kind(op.gate) != None

    def to_matrix(op: cirq.ops.GateOperation):
      mat = cirq.protocols.unitary(op.gate, None)
      if mat is None:
          return NotImplemented
      
      return cirq.ops.MatrixGate(mat).on(*op.qubits)

    qubit_to_index_dict = {q: i for i, q in enumerate(ordered_qubits)}
    time_offset = 0
    for moment in self:
      ops_by_gate = [
        cirq.decompose(op, fallback_decomposer=to_matrix, keep=has_qsim_kind)
        for op in moment
      ]
      moment_length = max(len(gate_ops) for gate_ops in ops_by_gate)

      # Gates must be added in time order.
      for gi in range(moment_length):
        for gate_ops in ops_by_gate:
          if gi >= len(gate_ops):
            continue
          qsim_op = gate_ops[gi]
          gate_kind = _cirq_gate_kind(qsim_op.gate)
          time = time_offset + gi
          qubits = [qubit_to_index_dict[q] for q in qsim_op.qubits]

          qsim_gate = qsim_op.gate
          qsim_qubits = qubits
          is_controlled = isinstance(qsim_op.gate, cirq.ops.ControlledGate)
          if is_controlled:
            control_qubits, control_values = _control_details(qsim_op.gate,
                                                              qubits)
            if control_qubits is None:
              # This gate has no valid control, and will be omitted.
              continue

            if qsim_gate.num_qubits() > 4:
              raise NotImplementedError(
              f'Received control gate on {gate.num_qubits()} target qubits; '
              + 'only up to 4-qubit gates are supported.')

            qsim_gate = qsim_gate.sub_gate
            qsim_qubits = qubits[qsim_op.gate.num_controls():]

          if gate_kind == qsim.kTwoQubitDiagonalGate or gate_kind == qsim.kThreeQubitDiagonalGate:
            qsim.add_diagonal_gate(time, qsim_qubits,
                                   qsim_gate._diag_angles_radians, qsim_circuit)
          elif gate_kind == qsim.kMatrixGate:
            flatten = lambda l : [val for i in l for val in [i.real, i.imag]]
            qsim.add_matrix_gate(time, qsim_qubits,
                                 flatten(list(cirq.unitary(qsim_gate).flat)),
                                 qsim_circuit)
          else:
            params = {
              p.strip('_'): val for p, val in vars(qsim_gate).items()
              if isinstance(val, float) or isinstance(val, int)
            }
            qsim.add_gate(gate_kind, time, qsim_qubits, params, qsim_circuit)

          if is_controlled:
            qsim.control_last_gate(control_qubits, control_values, qsim_circuit)
      time_offset += moment_length

    return qsim_circuit