-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #160 from QuTech-Delft/152-basic-implementation-ma…
…pper 152 basic implementation mapper
- Loading branch information
Showing
13 changed files
with
576 additions
and
69 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
from opensquirrel.mapper.general_mapper import Mapper, map_qubits | ||
from opensquirrel.mapper.simple_mappers import HardcodedMapper, IdentityMapper | ||
|
||
__all__ = ["map_qubits", "Mapper", "IdentityMapper", "HardcodedMapper"] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
"""This module contains generic mapping components.""" | ||
|
||
from __future__ import annotations | ||
|
||
from abc import ABC, abstractmethod | ||
|
||
from opensquirrel.squirrel_ir import Gate, Measure, SquirrelIR | ||
|
||
|
||
def map_qubits(squirrel_ir: SquirrelIR, mapper: Mapper) -> None: | ||
"""Map the virtual qubits in the `squirrel_ir` to physical qubits using `mapper`. | ||
Args: | ||
squirrel_ir: IR to apply mapping to. | ||
mapper: Mapping pass to use. | ||
""" | ||
|
||
mapping = mapper.map(squirrel_ir) | ||
|
||
for statement in squirrel_ir.statements: | ||
if isinstance(statement, (Gate, Measure)): | ||
statement.relabel(mapping) | ||
|
||
|
||
class Mapper(ABC): | ||
"""Base class for the Mapper pass.""" | ||
|
||
@abstractmethod | ||
def map(self, squirrel_ir: SquirrelIR) -> dict[int, int]: | ||
"""Produce a mapping from the virtual qubits in the `squirrel_ir` to the physical qubits. | ||
Args: | ||
squirrel_ir: IR to apply mapping to. | ||
Returns: | ||
Mapping from virtual qubits to physical qubits. | ||
""" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,59 @@ | ||
"""This module contains the following simple mappers: | ||
* IdentityMapper | ||
* HardcodedMapper | ||
""" | ||
|
||
from __future__ import annotations | ||
|
||
from collections.abc import Mapping | ||
from typing import SupportsInt | ||
|
||
from opensquirrel.mapper.general_mapper import Mapper | ||
from opensquirrel.squirrel_ir import SquirrelIR | ||
|
||
|
||
class IdentityMapper(Mapper): | ||
|
||
def map(self, squirrel_ir: SquirrelIR) -> dict[int, int]: | ||
"""Produce an IdentityMapping. | ||
Args: | ||
squirrel_ir: IR to map. | ||
Returns: | ||
Mapping from virtual qubits to physical qubits. Each virtual qubit is mapped to the physical qubit with | ||
the same index. | ||
""" | ||
return {i: i for i in range(squirrel_ir.number_of_qubits)} | ||
|
||
|
||
class HardcodedMapper(Mapper): | ||
|
||
def __init__(self, mapping: Mapping[SupportsInt, SupportsInt]) -> None: | ||
"""Init of the ``HardcodedMapper``. | ||
Args: | ||
mapping: Mapping with as keys the virtual qubits and as values the physical qubits. | ||
Raises: | ||
ValueError: If `mapping` is not a valid mapping. | ||
""" | ||
# Check if the provided mapping is valid | ||
self.mapping = {int(virtual_qubit): int(physical_qubit) for virtual_qubit, physical_qubit in mapping.items()} | ||
if set(self.mapping.keys()) != set(self.mapping.values()): | ||
raise ValueError("The set of physical qubits is not equal to the set of virtual qubits.") | ||
|
||
def map(self, squirrel_ir: SquirrelIR) -> dict[int, int]: | ||
"""Retrieve the hardcoded mapping. | ||
Args: | ||
squirrel_ir: IR to apply mapping to. | ||
Returns: | ||
Mapping from virtual qubits to physical qubits. | ||
""" | ||
if set(range(squirrel_ir.number_of_qubits)) != set(self.mapping.keys()): | ||
raise ValueError("Virtual qubits are not labeled correctly.") | ||
|
||
return self.mapping |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
import networkx as nx | ||
|
||
from opensquirrel.squirrel_ir import Gate, SquirrelIR | ||
|
||
|
||
def make_interaction_graph(squirrel_ir: SquirrelIR) -> nx.Graph: | ||
|
||
interaction_graph = nx.Graph() | ||
gates = (statement for statement in squirrel_ir.statements if isinstance(statement, Gate)) | ||
|
||
for gate in gates: | ||
target_qubits = gate.get_qubit_operands() | ||
if len(target_qubits) == 1: | ||
continue | ||
if len(target_qubits) > 2: | ||
raise ValueError( | ||
f"The gate {gate} acts on more than 2 qubits. The gate must be decomposed before an interaction graph " | ||
"can be made." | ||
) | ||
interaction_graph.add_edge(*target_qubits) | ||
|
||
return interaction_graph |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
"""Ths subpackage contains compatibility checks for the different compilation passes.""" | ||
|
||
from opensquirrel.utils.check_passes.check_mapper import check_mapper | ||
|
||
__all__ = ["check_mapper"] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,61 @@ | ||
"""This module contains checks for the ``Mapper`` pass.""" | ||
|
||
from __future__ import annotations | ||
|
||
from copy import deepcopy | ||
|
||
from opensquirrel.mapper.general_mapper import Mapper | ||
from opensquirrel.squirrel_ir import BlochSphereRotation, Comment, ControlledGate, Measure, Qubit, SquirrelIR | ||
|
||
|
||
def check_mapper(mapper: Mapper) -> None: | ||
"""Check if the `mapper` complies with the OpenSquirrel requirements. | ||
If an implementation of ``Mapper`` passes these checks it should be compatible with the ``Circuit.map_qubits`` | ||
method. | ||
Args: | ||
mapper: Mapper to check. | ||
""" | ||
|
||
assert isinstance(mapper, Mapper) | ||
|
||
squirrel_ir = SquirrelIR(number_of_qubits=10) | ||
_check_scenario(squirrel_ir, mapper) | ||
|
||
squirrel_ir = SquirrelIR(number_of_qubits=10) | ||
squirrel_ir.add_comment(Comment("comment")) | ||
squirrel_ir.add_gate(BlochSphereRotation(Qubit(42), (1, 0, 0), 1, 2)) | ||
squirrel_ir.add_gate(ControlledGate(Qubit(42), BlochSphereRotation.identity(Qubit(100)))) | ||
squirrel_ir.add_measurement(Measure(Qubit(42), (0, 0, 1))) | ||
_check_scenario(squirrel_ir, mapper) | ||
|
||
|
||
def _check_scenario(squirrel_ir: SquirrelIR, mapper: Mapper) -> None: | ||
"""Check if the given scenario can be mapped. | ||
Args: | ||
squirrel_ir: SquirrelIR containing the scenario to check against. | ||
mapping: Mapping to check. | ||
""" | ||
squirrel_ir_copy = deepcopy(squirrel_ir) | ||
mapping = mapper.map(squirrel_ir) | ||
|
||
assert squirrel_ir == squirrel_ir_copy, "A Mapper pass should not change the SquirrelIR." | ||
_check_mapping_format(mapping, squirrel_ir.number_of_qubits) | ||
|
||
|
||
def _check_mapping_format(mapping: dict[int, int], number_of_qubits: int) -> None: | ||
"""Check if the mapping has the expected format. | ||
Args: | ||
mapping: Mapping to check. | ||
n_qubits: Number of qubits in the circuit. | ||
""" | ||
assert isinstance( | ||
mapping, dict | ||
), f"Output mapping should be an instance of <class 'dict'>, but was of type {type(mapping)}" | ||
assert set(mapping.keys()) == set( | ||
mapping.values() | ||
), "The set of virtual qubits is not equal to the set of phyical qubits." | ||
assert set(range(number_of_qubits)) == set(mapping.keys()), "Virtual qubits are not labeled correctly." |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Empty file.
Oops, something went wrong.