def __init__(self, *, seed: 'cirq.RANDOM_STATE_OR_SEED_LIKE' = None): """ Args: seed: The random seed or generator to use when sampling. """ self.init = True self._prng = value.parse_random_state(seed)
def random_orthogonal( dim: int, *, random_state: value.RANDOM_STATE_LIKE = None) -> np.ndarray: """Returns a random orthogonal matrix distributed with Haar measure. Args: dim: The width and height of the matrix. random_state: A seed (int) or `np.random.RandomState` class to use when generating random values. If not set, defaults to using the module methods in `np.random`. Returns: The sampled orthogonal matrix. References: 'How to generate random matrices from the classical compact groups' http://arxiv.org/abs/math-ph/0609050 """ random_state = value.parse_random_state(random_state) m = random_state.randn(dim, dim) q, r = np.linalg.qr(m) d = np.diag(r) return q * (d / abs(d))
def __init__( self, seed: 'cirq.RANDOM_STATE_OR_SEED_LIKE' = None, rsum2_cutoff: float = 1e-3, sum_prob_atol: float = 1e-3, grouping: Optional[Dict['cirq.Qid', int]] = None, ): """Creates instance of `MPSSimulator`. Args: seed: The random seed to use for this simulator. rsum2_cutoff: We drop singular values so that the sum of the square of the dropped singular values divided by the sum of the square of all the singular values is less than rsum2_cutoff. This is related to the fidelity of the computation. If we have N 2D gates, then the estimated fidelity is (1 - rsum2_cutoff) ** N. sum_prob_atol: Because the computation is approximate, the sum of the probabilities is not 1.0. This parameter is the absolute deviation from 1.0 that is allowed. grouping: How to group qubits together, if None all are individual. """ self.init = True self._prng = value.parse_random_state(seed) self.rsum2_cutoff = rsum2_cutoff self.sum_prob_atol = sum_prob_atol self.grouping = grouping
def __init__( self, *, dtype: Type[np.number] = np.complex64, noise: 'cirq.NOISE_MODEL_LIKE' = None, seed: 'cirq.RANDOM_STATE_OR_SEED_LIKE' = None, ): """A sparse matrix simulator. Args: dtype: The `numpy.dtype` used by the simulation. One of `numpy.complex64` or `numpy.complex128`. noise: A noise model to apply while simulating. seed: The random seed to use for this simulator. """ if np.dtype(dtype).kind != 'c': raise ValueError( 'dtype must be a complex type but was {}'.format(dtype)) self._dtype = dtype self._prng = value.parse_random_state(seed) noise_model = devices.NoiseModel.from_noise_model_like(noise) if not protocols.has_mixture(noise_model): raise ValueError( 'noise must be unitary or mixture but was {}'.format( noise_model)) self.noise = noise_model
def __init__(self, circuit, device_graph: nx.Graph, *, max_search_radius: int = 1, initial_mapping: Optional[Dict[ops.Qid, ops.Qid]] = None, can_reorder: Callable[ [ops.Operation, ops.Operation], bool] = circuits.circuit_dag._disjoint_qubits, random_state: value.RANDOM_STATE_LIKE = None): self.prng = value.parse_random_state(random_state) self.device_graph = device_graph self.physical_distances: Dict[QidPair, int] = { (a, b): d for a, neighbor_distances in nx.shortest_path_length(device_graph) for b, d in neighbor_distances.items() } self.remaining_dag = circuits.CircuitDag.from_circuit( circuit, can_reorder=can_reorder) self.logical_qubits = list(self.remaining_dag.all_qubits()) self.physical_qubits = list(self.device_graph.nodes) self.edge_sets: Dict[int, List[Sequence[QidPair]]] = {} self.physical_ops: List[ops.Operation] = [] self.set_initial_mapping(initial_mapping) self.max_search_radius = max_search_radius
def __init__(self, qsim_options: dict = {}, seed: value.RANDOM_STATE_OR_SEED_LIKE = None): """Creates a new QSimSimulator using the given options and seed. Args: qsim_options: A map of circuit options for the simulator. These will be applied to all circuits run using this simulator. Accepted keys and their behavior are as follows: - 'f': int (> 0). Maximum size of fused gates. Default: 2. - 'r': int (> 0). Noisy repetitions (see below). Default: 1. - 't': int (> 0). Number of threads to run on. Default: 1. - 'v': int (>= 0). Log verbosity. Default: 0. See qsim/docs/usage.md for more details on these options. "Noisy repetitions" specifies how many repetitions to aggregate over when calculating expectation values for a noisy circuit. Note that this does not apply to other simulation types. seed: A random state or seed object, as defined in cirq.value. Raises: ValueError if internal keys 'c', 'i' or 's' are included in 'qsim_options'. """ if any(k in qsim_options for k in ('c', 'i', 's')): raise ValueError( 'Keys {"c", "i", "s"} are reserved for internal use and cannot be ' 'used in QSimCircuit instantiation.') self._prng = value.parse_random_state(seed) self.qsim_options = {'t': 1, 'f': 2, 'v': 0, 'r': 1} self.qsim_options.update(qsim_options)
def __init__( self, *, dtype: Type[np.number] = np.complex64, noise: 'cirq.NOISE_MODEL_LIKE' = None, seed: 'cirq.RANDOM_STATE_OR_SEED_LIKE' = None, ignore_measurement_results: bool = False, split_untangled_states: bool = False, ): """Initializes the simulator. Args: dtype: The `numpy.dtype` used by the simulation. noise: A noise model to apply while simulating. seed: The random seed to use for this simulator. ignore_measurement_results: If True, then the simulation will treat measurement as dephasing instead of collapsing process. This is only applicable to simulators that can model dephasing. split_untangled_states: If True, optimizes simulation by running unentangled qubit sets independently and merging those states at the end. """ self._dtype = dtype self._prng = value.parse_random_state(seed) self.noise = devices.NoiseModel.from_noise_model_like(noise) self._ignore_measurement_results = ignore_measurement_results self._split_untangled_states = split_untangled_states
def __init__( self, noise: 'cirq.NOISE_MODEL_LIKE' = None, seed: 'cirq.RANDOM_STATE_OR_SEED_LIKE' = None, simulation_options: 'cirq.contrib.quimb.mps_simulator.MPSOptions' = MPSOptions(), grouping: Optional[Dict['cirq.Qid', int]] = None, ): """Creates instance of `MPSSimulator`. Args: noise: A noise model to apply while simulating. seed: The random seed to use for this simulator. simulation_options: Numerical options for the simulation. grouping: How to group qubits together, if None all are individual. """ self.init = True noise_model = devices.NoiseModel.from_noise_model_like(noise) if not protocols.has_mixture(noise_model): raise ValueError( 'noise must be unitary or mixture but was {}'.format( noise_model)) self.noise = noise_model self.prng = value.parse_random_state(seed) self.simulation_options = simulation_options self.grouping = grouping
def __init__(self, seed: 'cirq.RANDOM_STATE_OR_SEED_LIKE' = None): """Creates instance of `CliffordSimulator`. Args: seed: The random seed to use for this simulator. """ self.init = True self._prng = value.parse_random_state(seed)
def __init__(self, qsim_options: dict = {}, seed: value.RANDOM_STATE_OR_SEED_LIKE = None): if any(k in qsim_options for k in ('c', 'i')): raise ValueError( 'Keys "c" & "i" are reserved for internal use and cannot be used in QSimCircuit instantiation.' ) self._prng = value.parse_random_state(seed) self.qsim_options = {'t': 1, 'f': 2, 'v': 0} self.qsim_options.update(qsim_options)
def test_empty_step_result(): q0 = cirq.LineQubit(0) state = ccq.mps_simulator.MPSState(qubits=(q0, ), prng=value.parse_random_state(0)) step_result = ccq.mps_simulator.MPSSimulatorStepResult( state, measurements={'0': [1]}) assert (str(step_result) == """0=1 TensorNetwork([ Tensor(shape=(2,), inds=('i_0',), tags=set()), ])""")
def test_tensor_index_names(): qubits = cirq.LineQubit.range(12) qubit_map = {qubit: i for i, qubit in enumerate(qubits)} state = ccq.mps_simulator.MPSState(qubits=qubit_map, prng=value.parse_random_state(0)) assert state.i_str(0) == "i_00" assert state.i_str(11) == "i_11" assert state.mu_str(0, 3) == "mu_0_3" assert state.mu_str(3, 0) == "mu_0_3"
def test_state_equal(): q0, q1 = cirq.LineQubit.range(2) state0 = ccq.mps_simulator.MPSState( qubits=(q0,), prng=value.parse_random_state(0), simulation_options=ccq.mps_simulator.MPSOptions(cutoff=1e-3, sum_prob_atol=1e-3), ) state1a = ccq.mps_simulator.MPSState( qubits=(q1,), prng=value.parse_random_state(0), simulation_options=ccq.mps_simulator.MPSOptions(cutoff=1e-3, sum_prob_atol=1e-3), ) state1b = ccq.mps_simulator.MPSState( qubits=(q1,), prng=value.parse_random_state(0), simulation_options=ccq.mps_simulator.MPSOptions(cutoff=1729.0, sum_prob_atol=1e-3), ) assert state0 == state0 assert state0 != state1a assert state1a != state1b
def measure(self, axes: Sequence[int], seed: 'cirq.RANDOM_STATE_OR_SEED_LIKE' = None) -> List[int]: """Measures the MPS. Args: axes: The axes to measure. seed: The random number seed to use. Returns: The measurements in axis order. """ return self._measure(axes, value.parse_random_state(seed))
def test_trial_result_str(): q0 = cirq.LineQubit(0) final_simulator_state = ccq.mps_simulator.MPSState( qubits=(q0, ), prng=value.parse_random_state(0), simulation_options=ccq.mps_simulator.MPSOptions(), ) result = ccq.mps_simulator.MPSTrialResult( params=cirq.ParamResolver({}), measurements={'m': np.array([[1]])}, final_simulator_state=final_simulator_state, ) assert 'output state: TensorNetwork' in str(result)
def sample( self, qubits: Sequence['cirq.Qid'], repetitions: int = 1, seed: 'cirq.RANDOM_STATE_OR_SEED_LIKE' = None, ) -> np.ndarray: prng = value.parse_random_state(seed) axes = self.get_axes(qubits) measurements = [] for _ in range(repetitions): state = self.state.copy() measurements.append([state._measure(i, prng) for i in axes]) return np.array(measurements, dtype=bool)
def sample(self, qubits: List[ops.Qid], repetitions: int = 1, seed: 'cirq.RANDOM_STATE_OR_SEED_LIKE' = None) -> np.ndarray: measurements = [] for _ in range(repetitions): measurements.append( self.state.perform_measurement(qubits, value.parse_random_state(seed), collapse_wavefunction=False)) return np.array(measurements, dtype=bool)
def _random_two_qubit_unitaries(num_samples: int, random_state: 'cirq.RANDOM_STATE_OR_SEED_LIKE'): # Randomly generated two-qubit unitaries and the KAK vectors (not canonical) kl = _local_two_qubit_unitaries(num_samples, random_state) kr = _local_two_qubit_unitaries(num_samples, random_state) prng = value.parse_random_state(random_state) # Generate the non-local part by explict matrix exponentiation. kak_vecs = prng.rand(num_samples, 3) * np.pi gens = np.einsum('...a,abc->...bc', kak_vecs, _kak_gens) evals, evecs = np.linalg.eigh(gens) A = np.einsum('...ab,...b,...cb', evecs, np.exp(1j * evals), evecs.conj()) return np.einsum('...ab,...bc,...cd', kl, A, kr), kak_vecs
def _get_random_combinations( n_library_circuits: int, n_combinations: int, *, pair_gen: Iterator[Tuple[List[QidPairT], Any]], random_state: 'cirq.RANDOM_STATE_OR_SEED_LIKE' = None, ) -> List[CircuitLibraryCombination]: """For qubit pairs, prepare a set of combinations to efficiently sample parallel two-qubit XEB circuits. This helper function should be called by one of `get_random_comibations_for_device`, `get_random_combinations_for_layer_circuit`, or `get_random_combinations_for_pairs` which define appropriate `pair_gen` arguments. Args: n_library_circuits: The number of circuits in your library. Likely the value passed to `generate_library_of_2q_circuits`. n_combinations: The number of combinations (with replacement) to generate using the library circuits. Since this function returns a `CircuitLibraryCombination`, the combinations will be represented by indexes between 0 and `n_library_circuits-1` instead of the circuits themselves. The more combinations, the more precise of an estimate for XEB fidelity estimation, but a corresponding increase in the number of circuits you must sample. pair_gen: A generator that yields tuples of (pairs, layer_meta) where pairs is a list of qubit pairs and layer_meta is additional data describing the "layer" assigned to the CircuitLibraryCombination.layer field. random_state: A random-state-like object to seed the random combination generation. Returns: A list of `CircuitLibraryCombination`, each corresponding to a layer generated from `pair_gen`. Each object has a `combinations` matrix of circuit indices of shape `(n_combinations, len(pairs))`. This returned list can be provided to `sample_2q_xeb_circuits` to efficiently sample parallel XEB circuits. """ rs = value.parse_random_state(random_state) combinations_by_layer = [] for pairs, layer in pair_gen: combinations = rs.randint(0, n_library_circuits, size=(n_combinations, len(pairs))) combinations_by_layer.append( CircuitLibraryCombination(layer=layer, combinations=combinations, pairs=pairs)) return combinations_by_layer
def sample( self, qubits: Sequence['cirq.Qid'], repetitions: int = 1, seed: 'cirq.RANDOM_STATE_OR_SEED_LIKE' = None, ) -> np.ndarray: measurements: Dict[str, List[np.ndarray]] = {} prng = value.parse_random_state(seed) for i in range(repetitions): op = ops.measure(*qubits, key=str(i)) state = self.state.copy() ch_form_args = ActOnStabilizerCHFormArgs(state, prng, measurements, self.qubits) protocols.act_on(op, ch_form_args) return np.array(list(measurements.values()), dtype=bool)
def get_random_combinations_for_device( n_library_circuits: int, n_combinations: int, device_graph: nx.Graph, *, pattern: Sequence[GridInteractionLayer] = HALF_GRID_STAGGERED_PATTERN, random_state: 'cirq.RANDOM_STATE_OR_SEED_LIKE' = None, ) -> List[CircuitLibraryCombination]: """For a given device, prepare a set of combinations to efficiently sample parallel two-qubit XEB circuits. Args: n_library_circuits: The number of circuits in your library. Likely the value passed to `generate_library_of_2q_circuits`. n_combinations: The number of combinations (with replacement) to generate using the library circuits. Since this function returns a `CircuitLibraryCombination`, the combinations will be represented by indexes between 0 and `n_library_circuits-1` instead of the circuits themselves. The more combinations, the more precise of an estimate for XEB fidelity estimation, but a corresponding increase in the number of circuits you must sample. device_graph: A graph whose nodes are qubits and whose edges represent the possibility of doing a two-qubit gate. This combined with the `pattern` argument determines which two qubit pairs are activated when. pattern: A sequence of `GridInteractionLayer`, each of which has a particular set of qubits that are activated simultaneously. These pairs of qubits are deduced by combining this argument with `device_graph`. random_state: A random-state-like object to seed the random combination generation. Returns: A list of `CircuitLibraryCombination`, each corresponding to an interaction layer in `pattern`. Each object has a `combinations` matrix of circuit indices of shape `(n_combinations, len(pairs))` where `len(pairs)` may be different for each entry (i.e. for each layer in `pattern`). This returned list can be provided to `sample_2q_xeb_circuits` to efficiently sample parallel XEB circuits. """ rs = value.parse_random_state(random_state) combinations_by_layer = [] for layer in pattern: pairs = sorted(_get_active_pairs(device_graph, layer)) combinations = rs.randint(0, n_library_circuits, size=(n_combinations, len(pairs))) combinations_by_layer.append( CircuitLibraryCombination(layer=layer, combinations=combinations, pairs=pairs) ) return combinations_by_layer
def sample( self, qubits: Sequence['cirq.Qid'], repetitions: int = 1, seed: 'cirq.RANDOM_STATE_OR_SEED_LIKE' = None, ) -> np.ndarray: measurements: List[List[int]] = [] for _ in range(repetitions): measurements.append( self.perform_measurement(qubits, value.parse_random_state(seed), collapse_state_vector=False)) return np.array(measurements, dtype=int)
def __init__(self, *, dtype: Type[np.number] = np.complex64, seed: 'cirq.RANDOM_STATE_OR_SEED_LIKE' = None): """A sparse matrix simulator. Args: dtype: The `numpy.dtype` used by the simulation. One of `numpy.complex64` or `numpy.complex128`. seed: The random seed to use for this simulator. """ if np.dtype(dtype).kind != 'c': raise ValueError( 'dtype must be a complex type but was {}'.format(dtype)) self._dtype = dtype self._prng = value.parse_random_state(seed)
def test_trial_result_str(): q0 = cirq.LineQubit(0) final_simulator_state = ccq.mps_simulator.MPSState( qubits=(q0, ), prng=value.parse_random_state(0), simulation_options=ccq.mps_simulator.MPSOptions(), ) assert (str( ccq.mps_simulator.MPSTrialResult( params=cirq.ParamResolver({}), measurements={'m': np.array([[1]])}, final_simulator_state=final_simulator_state, )) == """measurements: m=1 output state: TensorNetwork([ Tensor(shape=(2,), inds=('i_0',), tags=set()), ])""")
def to_cirq_result( self, params: study.ParamResolver = None, seed: 'cirq.RANDOM_STATE_OR_SEED_LIKE' = None, override_repetitions=None, ) -> study.Result: """Samples from the simulation probability result, producing a `cirq.Result`. The IonQ simulator returns the probabilities of different bitstrings. This converts such a representation to a randomly generated sample from the simulator. Note that it does this on every subsequent call of this method, so repeated calls do not produce the same `cirq.Result`s. When a job was created by the IonQ API, it had a number of repetitions and this is used, unless `override_repetitions` is set here. Args: params: Any parameters which were used to generated this result. seed: What to use for generating the randomness. If None, then `np.random` is used. If an integer, `np.random.RandomState(seed) is used. Otherwise if another randomness generator is used, it will be used. override_repetitions: Repetitions were supplied when the IonQ API ran the simulation, but different repetitions can be supplied here and will override. Returns: A `cirq.Result` corresponding to a sample from the probability distribution returned from the simulator. Raises: ValueError: If the circuit used to produce this result had no measurement gates (and hence no measurement keys). """ if len(self.measurement_dict()) == 0: raise ValueError( 'Can convert to cirq results only if the circuit had measurement gates ' 'with measurement keys.') rand = value.parse_random_state(seed) measurements = {} values, weights = zip(*list(self.probabilities().items())) indices = rand.choice(range(len(values)), p=weights, size=override_repetitions or self.repetitions()) rand_values = np.array(values)[indices] for key, targets in self.measurement_dict().items(): bits = [[(value >> (self.num_qubits() - target - 1)) & 1 for target in targets] for value in rand_values] measurements[key] = bits return study.Result(params=params or study.ParamResolver({}), measurements=measurements)
def test_trial_result_repr_pretty(): q0 = cirq.LineQubit(0) final_simulator_state = ccq.mps_simulator.MPSState( qubits=(q0, ), prng=value.parse_random_state(0), simulation_options=ccq.mps_simulator.MPSOptions(), ) result = ccq.mps_simulator.MPSTrialResult( params=cirq.ParamResolver({}), measurements={'m': np.array([[1]])}, final_simulator_state=final_simulator_state, ) cirq.testing.assert_repr_pretty_contains(result, 'output state: TensorNetwork') cirq.testing.assert_repr_pretty(result, "cirq.MPSTrialResult(...)", cycle=True)
def __init__( self, *, dtype: Type[np.number] = np.complex64, noise: 'cirq.NOISE_MODEL_LIKE' = None, seed: 'cirq.RANDOM_STATE_OR_SEED_LIKE' = None, ignore_measurement_results: bool = False, ): """Density matrix simulator. Args: dtype: The `numpy.dtype` used by the simulation. One of `numpy.complex64` or `numpy.complex128` noise: A noise model to apply while simulating. seed: The random seed to use for this simulator. ignore_measurement_results: if True, then the simulation will treat measurement as dephasing instead of collapsing process. Example: >>> (q0,) = cirq.LineQubit.range(1) >>> circuit = cirq.Circuit(cirq.H(q0), cirq.measure(q0)) Default case (ignore_measurement_results = False): >>> simulator = cirq.DensityMatrixSimulator() >>> result = simulator.run(circuit) The measurement result will be strictly one of 0 or 1. In the other case: >>> simulator = cirq.DensityMatrixSimulator( ... ignore_measurement_results = True) >>> result = simulator.run(circuit) The measurement result will be the maximally mixed state with equal probability for 0 and 1. """ if dtype not in {np.complex64, np.complex128}: raise ValueError( 'dtype must be complex64 or complex128, was {}'.format(dtype)) self._dtype = dtype self._prng = value.parse_random_state(seed) self.noise = devices.NoiseModel.from_noise_model_like(noise) self._ignore_measurement_results = ignore_measurement_results
def __init__( self, *, dtype: 'DTypeLike' = np.complex64, noise: 'cirq.NOISE_MODEL_LIKE' = None, seed: 'cirq.RANDOM_STATE_OR_SEED_LIKE' = None, ignore_measurement_results: bool = False, ): """Density matrix simulator. Args: dtype: The `numpy.dtype` used by the simulation. One of `numpy.complex64` or `numpy.complex128` noise: A noise model to apply while simulating. seed: The random seed to use for this simulator. ignore_measurement_results: if True, then the simulation will treat measurement as dephasing instead of collapsing process. Example: >>> (q0,) = cirq.LineQubit.range(1) >>> circuit = cirq.Circuit(cirq.H(q0), cirq.measure(q0)) Default case (ignore_measurement_results = False): >>> simulator = cirq.DensityMatrixSimulator() >>> result = simulator.run(circuit) The measurement result will be strictly one of 0 or 1. In the other case: >>> simulator = cirq.DensityMatrixSimulator( ... ignore_measurement_results = True) will raise a `ValueError` exception if you call `simulator.run` when `ignore_measurement_results` has been set to True (for more see https://github.com/quantumlib/Cirq/issues/2777). """ if dtype not in {np.complex64, np.complex128}: raise ValueError( f'dtype must be complex64 or complex128, was {dtype}') self._dtype = dtype self._prng = value.parse_random_state(seed) self.noise = devices.NoiseModel.from_noise_model_like(noise) self._ignore_measurement_results = ignore_measurement_results
def random_superposition(dim: int, *, random_state: value.RANDOM_STATE_LIKE = None ) -> np.ndarray: """Returns a random unit-length vector from the uniform distribution. Args: dim: The dimension of the vector. Returns: The sampled unit-length vector. """ random_state = value.parse_random_state(random_state) state_vector = random_state.randn(dim).astype(complex) state_vector += 1j * random_state.randn(dim) state_vector /= np.linalg.norm(state_vector) return state_vector
def sample( self, qubits: List[ops.Qid], repetitions: int = 1, seed: 'cirq.RANDOM_STATE_OR_SEED_LIKE' = None, ) -> np.ndarray: measurements = {} # type: Dict[str, List[np.ndarray]] for i in range(repetitions): self.state.apply_measurement( cirq.measure(*qubits, key=str(i)), measurements, value.parse_random_state(seed), collapse_state_vector=False, ) return np.array(list(measurements.values()), dtype=bool)