from dataclasses import dataclass


@dataclass
class Target:
    n_qubits: int
    basis_gates: set[str]
    coupling_map: list[tuple[int, int]]  # undirected edges
    gate_durations: dict[str, float] = None  # ns
    error_rates: dict[str, float] = None  # per gate


class Backend:
    def __init__(self, target: Target, backend_id: str):
        self._target = target
        self._id = backend_id

    @property
    def id(self) -> str:
        return self._id

    @property
    def target(self) -> Target:
        return self._target

    def supports(self, op: str, qubits: tuple[int, ...]) -> bool:
        if (
            op in ("x", "sx", "rz")
            and len(qubits) == 1
            and qubits[0] < self._target.n_qubits
        ):
            return True
        if op == "cx" and len(qubits) == 2:
            a, b = qubits
            return (a, b) in self._target.coupling_map or (
                b,
                a,
            ) in self._target.coupling_map
        return op == "measure"
