Ejemplo n.º 1
0
    def _brute_force_samples(
        self,
        initial_state: np.ndarray,
        circuit: circuits.Circuit,
        qubit_order: 'cirq.QubitOrderOrList',
        repetitions: int,
    ) -> Dict[str, np.ndarray]:
        """Repeatedly simulate a circuit in order to produce samples."""
        if repetitions == 0:
            return {
                key: np.empty(shape=[0, 1])
                for key in protocols.measurement_keys(circuit)
            }

        measurements: DefaultDict[
            str, List[np.ndarray]] = collections.defaultdict(list)
        for _ in range(repetitions):
            all_step_results = self._base_iterator(circuit,
                                                   initial_state=initial_state,
                                                   qubit_order=qubit_order)

            for step_result in all_step_results:
                for k, v in step_result.measurements.items():
                    measurements[k].append(np.array(v, dtype=np.uint8))
        return {k: np.array(v) for k, v in measurements.items()}
Ejemplo n.º 2
0
def _verify_unique_measurement_keys(circuit: circuits.Circuit):
    result = collections.Counter(
        key for op in ops.flatten_op_tree(iter(circuit)) for key in protocols.measurement_keys(op)
    )
    if result:
        duplicates = [k for k, v in result.most_common() if v > 1]
        if duplicates:
            raise ValueError('Measurement key {} repeated'.format(",".join(duplicates)))
Ejemplo n.º 3
0
    def __post_init__(self):
        if not isinstance(self.circuit, circuits.FrozenCircuit):
            raise TypeError(
                f'Expected circuit of type FrozenCircuit, got: {type(self.circuit)!r}'
            )

        # Ensure that the circuit is invertible if the repetitions are negative.
        if self.repetitions < 0:
            try:
                protocols.inverse(self.circuit.unfreeze())
            except TypeError:
                raise ValueError(
                    f'repetitions are negative but the circuit is not invertible'
                )

        # Initialize repetition_ids to default, if unspecified. Else, validate their length.
        loop_size = abs(self.repetitions)
        if not self.repetition_ids:
            object.__setattr__(self, 'repetition_ids',
                               self._default_repetition_ids())
        elif len(self.repetition_ids) != loop_size:
            raise ValueError(
                f'Expected repetition_ids to be a list of length {loop_size}, '
                f'got: {self.repetition_ids}')

        # Disallow mapping to keys containing the `MEASUREMENT_KEY_SEPARATOR`
        for mapped_key in self.measurement_key_map.values():
            if MEASUREMENT_KEY_SEPARATOR in mapped_key:
                raise ValueError(
                    f'Mapping to invalid key: {mapped_key}. "{MEASUREMENT_KEY_SEPARATOR}" '
                    'is not allowed for measurement keys in a CircuitOperation'
                )

        # Validate the keys for all direct child measurements. They are not allowed to contain
        # `MEASUREMENT_KEY_SEPARATOR`
        for _, op in self.circuit.findall_operations(lambda op: not isinstance(
                op, CircuitOperation) and protocols.is_measurement(op)):
            for key in protocols.measurement_keys(op):
                key = self.measurement_key_map.get(key, key)
                if MEASUREMENT_KEY_SEPARATOR in key:
                    raise ValueError(
                        f'Measurement {op} found to have invalid key: {key}. '
                        f'"{MEASUREMENT_KEY_SEPARATOR}" is not allowed for measurement keys '
                        'in a CircuitOperation. Consider remapping the key using '
                        '`measurement_key_map` in the CircuitOperation constructor.'
                    )

        # Disallow qid mapping dimension conflicts.
        for q, q_new in self.qubit_map.items():
            if q_new.dimension != q.dimension:
                raise ValueError(
                    f'Qid dimension conflict.\nFrom qid: {q}\nTo qid: {q_new}')

        # Ensure that param_resolver is converted to an actual ParamResolver.
        object.__setattr__(self, 'param_resolver',
                           study.ParamResolver(self.param_resolver))
Ejemplo n.º 4
0
    def _run_sweep_repeat(self, circuit: circuits.Circuit,
                          repetitions: int) -> Dict[str, np.ndarray]:
        if repetitions == 0:
            return {
                key: np.empty(shape=[0, 1])
                for key in protocols.measurement_keys(circuit)
            }

        measurements: DefaultDict[
            str, List[np.ndarray]] = collections.defaultdict(list)
        for _ in range(repetitions):
            all_step_results = self._base_iterator(
                circuit, qubit_order=ops.QubitOrder.DEFAULT, initial_state=0)

            for step_result in all_step_results:
                for k, v in step_result.measurements.items():
                    measurements[k].append(np.array(v, dtype=np.uint8))
        return {k: np.array(v) for k, v in measurements.items()}
Ejemplo n.º 5
0
 def _decompose_(self) -> 'cirq.OP_TREE':
     result = self.circuit.unfreeze()
     result = result.transform_qubits(lambda q: self.qubit_map.get(q, q))
     if self.repetitions < 0:
         result = result**-1
     result = protocols.with_measurement_key_mapping(
         result, self.measurement_key_map)
     result = protocols.resolve_parameters(result,
                                           self.param_resolver,
                                           recursive=False)
     # repetition_ids don't need to be taken into account if the circuit has no measurements
     # or if repetition_ids are unset.
     if self.repetition_ids is None or not protocols.is_measurement(result):
         return list(result.all_operations()) * abs(self.repetitions)
     # If it's a measurement circuit with repetitions/repetition_ids, prefix the repetition_ids
     # to measurements. Details at https://tinyurl.com/measurement-repeated-circuitop.
     ops = []  # type: List[cirq.Operation]
     for parent_id in self.repetition_ids:
         for op in result.all_operations():
             if isinstance(op, CircuitOperation):
                 # For a CircuitOperation, prefix the current repetition_id to the children
                 # repetition_ids.
                 ops.append(
                     op.with_repetition_ids(
                         # If `op.repetition_ids` is None, this will return `[parent_id]`.
                         cartesian_product_of_string_lists(
                             [parent_id], op.repetition_ids)))
             elif protocols.is_measurement(op):
                 # For a non-CircuitOperation measurement, prefix the current repetition_id
                 # to the children measurement keys. Implemented by creating a mapping and
                 # using the with_measurement_key_mapping protocol.
                 ops.append(
                     protocols.with_measurement_key_mapping(
                         op,
                         key_map={
                             key:
                             f'{MEASUREMENT_KEY_SEPARATOR.join([parent_id, key])}'
                             for key in protocols.measurement_keys(op)
                         },
                     ))
             else:
                 ops.append(op)
     return ops
Ejemplo n.º 6
0
    def _run(self, circuit: circuits.Circuit,
             repetitions: int) -> Dict[str, np.ndarray]:

        measurements: Dict[str, List[int]] = {
            key: []
            for key in protocols.measurement_keys(circuit)
        }
        qubits = circuit.all_qubits()

        for _ in range(repetitions):
            state = ActOnCliffordTableauArgs(
                CliffordTableau(num_qubits=len(qubits)),
                qubits=list(qubits),
                prng=self._prng,
                log_of_measurement_results={},
            )
            for op in circuit.all_operations():
                protocols.act_on(op, state)

            for k, v in state.log_of_measurement_results.items():
                measurements[k].append(v)

        return {k: np.array(v) for k, v in measurements.items()}
Ejemplo n.º 7
0
    def _run(self, circuit: circuits.Circuit,
             repetitions: int) -> Dict[str, np.ndarray]:

        measurements: Dict[str, List[int]] = {
            key: []
            for key in protocols.measurement_keys(circuit)
        }
        axes_map = {q: i for i, q in enumerate(circuit.all_qubits())}

        for _ in range(repetitions):
            state = ActOnCliffordTableauArgs(
                CliffordTableau(num_qubits=len(axes_map)),
                axes=(),
                prng=self._prng,
                log_of_measurement_results={},
            )
            for op in circuit.all_operations():
                state.axes = tuple(axes_map[q] for q in op.qubits)
                protocols.act_on(op, state)

            for k, v in state.log_of_measurement_results.items():
                measurements[k].append(v)

        return {k: np.array(v) for k, v in measurements.items()}