Ejemplo n.º 1
0
def map_moments(
    circuit: CIRCUIT_TYPE,
    map_func: Callable[[circuits.Moment, int],
                       Union[circuits.Moment, Sequence[circuits.Moment]]],
    *,
    deep: bool = False,
) -> CIRCUIT_TYPE:
    """Applies local transformation on moments, by calling `map_func(moment)` for each moment.

    Args:
        circuit: Input circuit to apply the transformations on. The input circuit is not mutated.
        map_func: Mapping function from (cirq.Moment, moment_index) to a sequence of moments.
        deep: If true, `map_func` will be recursively applied to circuits wrapped inside
            any circuit operations contained within `circuit`.

    Returns:
        Copy of input circuit with mapped moments.
    """
    mutable_circuit = circuit.unfreeze(copy=False)
    if deep:
        batch_replace = []
        for i, op in circuit.findall_operations(
                lambda o: isinstance(o.untagged, circuits.CircuitOperation)):
            op_untagged = cast(circuits.CircuitOperation, op.untagged)
            mapped_op = op_untagged.replace(circuit=map_moments(
                op_untagged.mapped_circuit(), map_func, deep=deep).freeze())
            batch_replace.append((i, op, mapped_op))
        mutable_circuit = circuit.unfreeze(copy=True)
        mutable_circuit.batch_replace(batch_replace)
    return _create_target_circuit_type(
        (map_func(mutable_circuit[i], i) for i in range(len(mutable_circuit))),
        circuit)
Ejemplo n.º 2
0
def unroll_circuit_op_greedy_frontier(
    circuit: CIRCUIT_TYPE, *,
    tags_to_check=(MAPPED_CIRCUIT_OP_TAG, )) -> CIRCUIT_TYPE:
    """Unrolls (tagged) `cirq.CircuitOperation`s by inserting operations inline at qubit frontier.

    Each matching `cirq.CircuitOperation` is replaced by inserting underlying operations using the
    `circuit.insert_at_frontier` method. The greedy approach attempts to reuse any available space
    in existing moments on the right of circuit_op before inserting new moments.

    Args:
        circuit: Input circuit to apply the transformations on. The input circuit is not mutated.
        tags_to_check: If specified, only circuit operations tagged with one of the `tags_to_check`
            are unrolled.

    Returns:
        Copy of input circuit with (Tagged) CircuitOperation's expanded inline at qubit frontier.
    """
    unrolled_circuit = circuit.unfreeze(copy=True)
    frontier: Dict['cirq.Qid', int] = defaultdict(lambda: 0)
    for idx, op in circuit.findall_operations(
            lambda op: _check_circuit_op(op, tags_to_check)):
        idx = max(idx, max(frontier[q] for q in op.qubits))
        unrolled_circuit.clear_operations_touching(op.qubits, [idx])
        frontier = unrolled_circuit.insert_at_frontier(
            protocols.decompose_once(op), idx, frontier)
    return _to_target_circuit_type(unrolled_circuit, circuit)
Ejemplo n.º 3
0
def unroll_circuit_op_greedy_earliest(
    circuit: CIRCUIT_TYPE, *,
    tags_to_check=(MAPPED_CIRCUIT_OP_TAG, )) -> CIRCUIT_TYPE:
    """Unrolls (tagged) `cirq.CircuitOperation`s by inserting operations using EARLIEST strategy.

    Each matching `cirq.CircuitOperation` is replaced by inserting underlying operations using the
    `cirq.InsertStrategy.EARLIEST` strategy. The greedy approach attempts to minimize circuit depth
    of the resulting circuit.

    Args:
        circuit: Input circuit to apply the transformations on. The input circuit is not mutated.
        tags_to_check: If specified, only circuit operations tagged with one of the `tags_to_check`
            are unrolled.

    Returns:
        Copy of input circuit with (Tagged) CircuitOperation's expanded using EARLIEST strategy.
    """
    batch_removals = [
        *circuit.findall_operations(
            lambda op: _check_circuit_op(op, tags_to_check))
    ]
    batch_inserts = [(i, protocols.decompose_once(op))
                     for i, op in batch_removals]
    unrolled_circuit = circuit.unfreeze(copy=True)
    unrolled_circuit.batch_remove(batch_removals)
    unrolled_circuit.batch_insert(batch_inserts)
    return _to_target_circuit_type(unrolled_circuit, circuit)
Ejemplo n.º 4
0
def unroll_circuit_op_greedy_earliest(
    circuit: CIRCUIT_TYPE,
    *,
    deep: bool = False,
    tags_to_check: Optional[Sequence[Hashable]] = (MAPPED_CIRCUIT_OP_TAG, ),
) -> CIRCUIT_TYPE:
    """Unrolls (tagged) `cirq.CircuitOperation`s by inserting operations using EARLIEST strategy.

    Each matching `cirq.CircuitOperation` is replaced by inserting underlying operations using the
    `cirq.InsertStrategy.EARLIEST` strategy. The greedy approach attempts to minimize circuit depth
    of the resulting circuit.

    Args:
        circuit: Input circuit to apply the transformations on. The input circuit is not mutated.
        deep: If true, the transformer primitive will be recursively applied to all circuits
            wrapped inside circuit operations.
        tags_to_check: If specified, only circuit operations tagged with one of the `tags_to_check`
            are unrolled.

    Returns:
        Copy of input circuit with (Tagged) CircuitOperation's expanded using EARLIEST strategy.
    """
    batch_replace = []
    batch_remove = []
    batch_insert = []
    for i, op in circuit.findall_operations(
            lambda o: isinstance(o.untagged, circuits.CircuitOperation)):
        op_untagged = cast(circuits.CircuitOperation, op.untagged)
        if deep:
            op_untagged = op_untagged.replace(
                circuit=unroll_circuit_op_greedy_earliest(
                    op_untagged.circuit,
                    deep=deep,
                    tags_to_check=tags_to_check))
        if tags_to_check is None or set(tags_to_check).intersection(op.tags):
            batch_remove.append((i, op))
            batch_insert.append(
                (i, op_untagged.mapped_circuit().all_operations()))
        elif deep:
            batch_replace.append((i, op, op_untagged.with_tags(*op.tags)))
    unrolled_circuit = circuit.unfreeze(copy=True)
    unrolled_circuit.batch_replace(batch_replace)
    unrolled_circuit.batch_remove(batch_remove)
    unrolled_circuit.batch_insert(batch_insert)
    return _to_target_circuit_type(unrolled_circuit, circuit)
Ejemplo n.º 5
0
def map_moments(
    circuit: CIRCUIT_TYPE,
    map_func: Callable[[circuits.Moment, int],
                       Union[circuits.Moment, Sequence[circuits.Moment]]],
    *,
    tags_to_ignore: Sequence[Hashable] = (),
    deep: bool = False,
) -> CIRCUIT_TYPE:
    """Applies local transformation on moments, by calling `map_func(moment)` for each moment.

    Args:
        circuit: Input circuit to apply the transformations on. The input circuit is not mutated.
        map_func: Mapping function from (cirq.Moment, moment_index) to a sequence of moments.
        tags_to_ignore: Tagged circuit operations marked with any of `tags_to_ignore` will be
            ignored when recursively applying the transformer primitive to sub-circuits, given
            deep=True.
        deep: If true, `map_func` will be recursively applied to circuits wrapped inside
            any circuit operations contained within `circuit`.

    Returns:
        Copy of input circuit with mapped moments.
    """
    mutable_circuit = circuit.unfreeze(copy=False)
    if deep:
        batch_replace = []
        for i, op in circuit.findall_operations(
                lambda o: isinstance(o.untagged, circuits.CircuitOperation)):
            if set(op.tags).intersection(tags_to_ignore):
                continue
            op_untagged = cast(circuits.CircuitOperation, op.untagged)
            mapped_op = op_untagged.replace(
                circuit=map_moments(op_untagged.circuit,
                                    map_func,
                                    tags_to_ignore=tags_to_ignore,
                                    deep=deep)).with_tags(*op.tags)
            batch_replace.append((i, op, mapped_op))
        mutable_circuit = circuit.unfreeze(copy=True)
        mutable_circuit.batch_replace(batch_replace)
    return _create_target_circuit_type(
        (map_func(mutable_circuit[i], i) for i in range(len(mutable_circuit))),
        circuit)
Ejemplo n.º 6
0
def unroll_circuit_op_greedy_frontier(
    circuit: CIRCUIT_TYPE,
    *,
    deep: bool = False,
    tags_to_check: Optional[Sequence[Hashable]] = (MAPPED_CIRCUIT_OP_TAG, ),
) -> CIRCUIT_TYPE:
    """Unrolls (tagged) `cirq.CircuitOperation`s by inserting operations inline at qubit frontier.

    Each matching `cirq.CircuitOperation` is replaced by inserting underlying operations using the
    `circuit.insert_at_frontier` method. The greedy approach attempts to reuse any available space
    in existing moments on the right of circuit_op before inserting new moments.

    Args:
        circuit: Input circuit to apply the transformations on. The input circuit is not mutated.
        deep: If true, the transformer primitive will be recursively applied to all circuits
            wrapped inside circuit operations.
        tags_to_check: If specified, only circuit operations tagged with one of the `tags_to_check`
            are unrolled.

    Returns:
        Copy of input circuit with (Tagged) CircuitOperation's expanded inline at qubit frontier.
    """
    unrolled_circuit = circuit.unfreeze(copy=True)
    frontier: Dict['cirq.Qid', int] = defaultdict(lambda: 0)
    idx = 0
    while idx < len(unrolled_circuit):
        for op in unrolled_circuit[idx].operations:
            # Don't touch stuff inserted by unrolling previous circuit ops.
            if not isinstance(op.untagged, circuits.CircuitOperation):
                continue
            if any(frontier[q] > idx for q in op.qubits):
                continue
            op_untagged = cast(circuits.CircuitOperation, op.untagged)
            if deep:
                op_untagged = op_untagged.replace(
                    circuit=unroll_circuit_op_greedy_frontier(
                        op_untagged.circuit,
                        deep=deep,
                        tags_to_check=tags_to_check))
            if tags_to_check is None or set(tags_to_check).intersection(
                    op.tags):
                unrolled_circuit.clear_operations_touching(op.qubits, [idx])
                frontier = unrolled_circuit.insert_at_frontier(
                    op_untagged.mapped_circuit().all_operations(), idx,
                    frontier)
            elif deep:
                unrolled_circuit.batch_replace([
                    (idx, op, op_untagged.with_tags(*op.tags))
                ])
        idx += 1
    return _to_target_circuit_type(unrolled_circuit, circuit)
Ejemplo n.º 7
0
def unroll_circuit_op_greedy_earliest(
    circuit: CIRCUIT_TYPE,
    *,
    deep: bool = False,
    tags_to_check: Optional[Sequence[Hashable]] = (MAPPED_CIRCUIT_OP_TAG, ),
) -> CIRCUIT_TYPE:
    """Unrolls (tagged) `cirq.CircuitOperation`s by inserting operations using EARLIEST strategy.

    Each matching `cirq.CircuitOperation` is replaced by inserting underlying operations using the
    `cirq.InsertStrategy.EARLIEST` strategy. The greedy approach attempts to minimize circuit depth
    of the resulting circuit.

    Args:
        circuit: Input circuit to apply the transformations on. The input circuit is not mutated.
        deep: If True, `unroll_circuit_op_greedy_earliest` is recursively called on all circuit
            operations matching `tags_to_check`.
        tags_to_check: If specified, only circuit operations tagged with one of the `tags_to_check`
            are unrolled.

    Returns:
        Copy of input circuit with (Tagged) CircuitOperation's expanded using EARLIEST strategy.
    """
    batch_removals = [
        *circuit.findall_operations(
            lambda op: _check_circuit_op(op, tags_to_check))
    ]
    batch_inserts = []
    for i, op in batch_removals:
        sub_circuit = cast(circuits.CircuitOperation,
                           op.untagged).mapped_circuit()
        sub_circuit = (unroll_circuit_op_greedy_earliest(
            sub_circuit, deep=deep, tags_to_check=tags_to_check)
                       if deep else sub_circuit)
        batch_inserts += [(i, sub_circuit.all_operations())]
    unrolled_circuit = circuit.unfreeze(copy=True)
    unrolled_circuit.batch_remove(batch_removals)
    unrolled_circuit.batch_insert(batch_inserts)
    return _to_target_circuit_type(unrolled_circuit, circuit)
Ejemplo n.º 8
0
def unroll_circuit_op_greedy_frontier(
    circuit: CIRCUIT_TYPE,
    *,
    deep: bool = False,
    tags_to_check: Optional[Sequence[Hashable]] = (MAPPED_CIRCUIT_OP_TAG, ),
) -> CIRCUIT_TYPE:
    """Unrolls (tagged) `cirq.CircuitOperation`s by inserting operations inline at qubit frontier.

    Each matching `cirq.CircuitOperation` is replaced by inserting underlying operations using the
    `circuit.insert_at_frontier` method. The greedy approach attempts to reuse any available space
    in existing moments on the right of circuit_op before inserting new moments.

    Args:
        circuit: Input circuit to apply the transformations on. The input circuit is not mutated.
        deep: If True, `unroll_circuit_op_greedy_frontier` is recursively called on all circuit
            operations matching `tags_to_check`.
        tags_to_check: If specified, only circuit operations tagged with one of the `tags_to_check`
            are unrolled.

    Returns:
        Copy of input circuit with (Tagged) CircuitOperation's expanded inline at qubit frontier.
    """
    unrolled_circuit = circuit.unfreeze(copy=True)
    frontier: Dict['cirq.Qid', int] = defaultdict(lambda: 0)
    for idx, op in circuit.findall_operations(
            lambda op: _check_circuit_op(op, tags_to_check)):
        idx = max(idx, max(frontier[q] for q in op.qubits))
        unrolled_circuit.clear_operations_touching(op.qubits, [idx])
        sub_circuit = cast(circuits.CircuitOperation,
                           op.untagged).mapped_circuit()
        sub_circuit = (unroll_circuit_op_greedy_earliest(
            sub_circuit, deep=deep, tags_to_check=tags_to_check)
                       if deep else sub_circuit)
        frontier = unrolled_circuit.insert_at_frontier(
            sub_circuit.all_operations(), idx, frontier)
    return _to_target_circuit_type(unrolled_circuit, circuit)