Qiskit/qiskit_humaneval_hard huggingface dataset:
Return a list of density matrices whose mutual information is greater than the given tolerance.
You must implement this using a function named `mutual_information_dataset` with the following arguments: ε.

Solution:
from qiskit.quantum_info import mutual_information, random_density_matrix

def mutual_information_dataset(ε):
    mutual_information_list = []
    while len(mutual_information_list)<= 9:
        density_matrix = random_density_matrix(dims = 4)
        if mutual_information(density_matrix) >= ε:
            mutual_information_list.append(density_matrix)
    return mutual_information_list


Test:
from qiskit.quantum_info import mutual_information, random_density_matrix
def check(candidate):
    from qiskit.quantum_info import mutual_information, DensityMatrix, random_density_matrix
    import numpy as np

    tolerances = [0.1, 0.5, 1.0]  # Different values of ε to test
    num_matrices = 10

    for tol in tolerances:
        can_list = candidate(tol)

        # Check output type
        assert isinstance(can_list, list), "Output should be a list"
        assert len(can_list) == num_matrices, f"Expected {num_matrices} density matrices, but got {len(can_list)}"

        for i, item in enumerate(can_list):
            # Check if each item is a DensityMatrix
            assert isinstance(item, DensityMatrix), f"Item {i} is not a DensityMatrix"

            # Ensure mutual information is above ε
            assert mutual_information(item) >= tol, f"Mutual information of matrix {i} is less than {tol}"

            # Validate that the density matrix is properly normalized (trace = 1)
            assert np.isclose(item.trace(), 1, atol=1e-3), f"Density matrix {i} trace is not 1"

            # Ensure the density matrix is Hermitian
            assert np.allclose(item.data, item.data.conj().T), f"Density matrix {i} is not Hermitian"

            # Ensure the density matrix is positive semidefinite
            eigenvalues = np.linalg.eigvalsh(item.data)
            assert np.all(eigenvalues >= -1e-10), f"Density matrix {i} has negative eigenvalues (not positive semidefinite)"

check(mutual_information_dataset)
Return the schmidt decomposition coefficients and the subsystem vectors for the given density matrix and partition.
You must implement this using a function named `schmidt_test` with the following arguments: data, qargs_B.

Solution:
from qiskit.quantum_info import schmidt_decomposition

def schmidt_test(data, qargs_B):
    return schmidt_decomposition(data, qargs_B)


Test:
from qiskit.quantum_info import schmidt_decomposition
def check(candidate):
    from qiskit.quantum_info import random_statevector
    rs = random_statevector(dims = 16)
    qargs = [0,1]
    schmidt_decomp = candidate(rs, qargs)
    for _, item in enumerate(schmidt_decomp):
        assert item[0]>=0, "Schmidt coefficients must be real"
        assert item[1].dims() == (2,2), "The dimension of the first subsystem doesn't match"
        assert item[2].dims() == (2,2), "The dimension of the second subsystem doesn't match"

check(schmidt_test)
Return a list of ten probability vectors each of length 16 whose shannon entropy is greater than a given value.
You must implement this using a function named `shannon_entropy_data` with the following arguments: ε.

Solution:
from qiskit.quantum_info import shannon_entropy
import numpy as np

def shannon_entropy_data(ε):
    shannon_data = []
    while len(shannon_data) <= 9:
        rand_prob = np.random.randn(16)
        if shannon_entropy(rand_prob) >= ε:
            shannon_data.append(rand_prob)
    return shannon_data


Test:
from qiskit.quantum_info import shannon_entropy
import numpy as np
def check(candidate):
    tol = 1
    can_list = candidate(tol)
    assert len(can_list) == 10, " The length of the list is not 10"
    for _, item in enumerate(can_list):
        assert shannon_entropy(item)>= tol, "Shannon entropy not greater than given value"
        assert len(item) == 16, "The length of the probability vector is not 16"

check(shannon_entropy_data)
Return a list of ten anticommutators for the given pauli.
You must implement this using a function named `anticommutators` with the following arguments: pauli.

Solution:
from qiskit.quantum_info import anti_commutator, SparsePauliOp
from qiskit.quantum_info import random_pauli
import numpy as np

def anticommutators(pauli):
    def is_multiple_of_identity(matrix):
        identity_matrix = np.eye(matrix.shape[0])
        scalar = matrix[0,0]
        return np.allclose(matrix, scalar*identity_matrix)
    num_qubits = pauli.num_qubits
    anticommutator_list = []
    while len(anticommutator_list) <= 9:
        random_pauli_value = SparsePauliOp(random_pauli(num_qubits))
        anti_commutator_value = anti_commutator(pauli, random_pauli_value)
        if is_multiple_of_identity(anti_commutator_value.to_matrix()):
            anticommutator_list.append(random_pauli_value)
    return anticommutator_list


Test:
from qiskit.quantum_info import anti_commutator, SparsePauliOp
from qiskit.quantum_info import random_pauli
import numpy as np
def check(candidate):
    def is_multiple_of_identity(matrix):
        if matrix.shape[0] != matrix.shape[1]:
            return False  # Not a square matrix
        identity_matrix = np.eye(matrix.shape[0])
        scalar = matrix[0,0]
        return np.allclose(matrix, scalar*identity_matrix)
    test_pauli = SparsePauliOp(["XI"])
    can_anticommutators = candidate(test_pauli)
    assert len(can_anticommutators) == 10, "The number of anticommutators is not 10"
    for _,item in enumerate(can_anticommutators):
        assert is_multiple_of_identity(anti_commutator(item, test_pauli).to_matrix()), "The operator doesn't anticommute with the given pauli operator"

check(anticommutators)
Return a list of 10 single qubit density matrices whose purity is greater than 0.5.
You must implement this using a function named `purity_dataset` with no arguments.

Solution:
from qiskit.quantum_info import random_density_matrix, purity, DensityMatrix
import numpy as np

def purity_dataset():
    purity_dataset_list = []
    while len(purity_dataset_list)<=9:
        rand_density_matrix = random_density_matrix(dims=2)
        if np.abs(purity(rand_density_matrix))>=0.5:
            purity_dataset_list.append(rand_density_matrix)
    return purity_dataset_list


Test:
from qiskit.quantum_info import random_density_matrix, purity, DensityMatrix
import numpy as np
def check(candidate):
    can_list = candidate()
    assert len(can_list) == 10, "Number of density matrices is not 10"
    for _, item in enumerate(can_list):
        assert isinstance(item, DensityMatrix)
        assert np.abs(purity(item))>=0.5, "Purity of the denisty matrices is not less than 0.5"

check(purity_dataset)
Return a list of ten pairs of one qubit state vectors whose state fidelity is greater than 0.9.
You must implement this using a function named `fidelity_dataset` with no arguments.

Solution:
from qiskit.quantum_info import random_statevector, state_fidelity, Statevector

def fidelity_dataset():
    fidelity_dataset_list = []
    while len(fidelity_dataset_list)<=9:
        sv_1 = random_statevector(2)
        sv_2 = random_statevector(2)
        if state_fidelity(sv_1, sv_2) >= 0.9:
            fidelity_dataset_list.append((sv_1,sv_2))
    return fidelity_dataset_list


Test:
from qiskit.quantum_info import random_statevector, state_fidelity, Statevector
def check(candidate):
    can_list = candidate()
    assert len(can_list) == 10, "Length of returned list is not 10"
    for _, item in enumerate(can_list):
        assert isinstance(item[0], Statevector)
        assert isinstance(item[1], Statevector)
        assert(state_fidelity(item[0], item[1]))>=0.9, "State fidelity of the returned pairs is less than 0.9"

check(fidelity_dataset)
Return a list of 10 density matrices whose concurrence is 0.
You must implement this using a function named `concurrence_dataset` with no arguments.

Solution:
from qiskit.quantum_info import random_density_matrix, concurrence, DensityMatrix

def concurrence_dataset():
    concurrence_dataset_list = []
    while len(concurrence_dataset_list) <= 9:
        rand_mat = random_density_matrix(dims = 4)
        if concurrence(rand_mat) == 0:
            concurrence_dataset_list.append(rand_mat)
    return concurrence_dataset_list


Test:
from qiskit.quantum_info import random_density_matrix, concurrence, DensityMatrix
def check(candidate):
    can_mat_list = candidate()
    assert len(can_mat_list) == 10, "The list doesn't contain 10 elements"
    for _, item in enumerate(can_mat_list):
        assert isinstance(item, DensityMatrix)
        assert concurrence(item) == 0, "The concurrence of the density matrix is not 0"

check(concurrence_dataset)
Return the inverse qft circuit for n qubits.
You must implement this using a function named `qft_inverse` with the following arguments: n.

Solution:
from qiskit.circuit.library import QFT
from qiskit import QuantumCircuit
from qiskit.quantum_info import Operator

def qft_inverse(n):
    return QFT(num_qubits=n, approximation_degree=0, inverse=True)


Test:
from qiskit.circuit.library import QFT
from qiskit import QuantumCircuit
from qiskit.quantum_info import Operator
def check(candidate):
    from qiskit.circuit.library import QFT
    from qiskit import QuantumCircuit
    from qiskit.quantum_info import Operator

    # Test multiple values of n
    for n in [1, 2, 3, 5, 8, 10]:
        candidate_circ = candidate(n)

        # Ensure the result is a QuantumCircuit
        assert isinstance(candidate_circ, QuantumCircuit), "Returned object is not a QuantumCircuit"

        # Ensure the circuit has the correct number of qubits
        assert candidate_circ.num_qubits == n, f"Expected {n} qubits, but got {candidate_circ.num_qubits}"

        # Verify that the returned circuit is equivalent to the expected inverse QFT circuit
        candidate_op = Operator(candidate_circ)
        test_circ = QFT(n, approximation_degree=0, inverse=True)
        test_op = Operator(test_circ)

        assert test_op.equiv(candidate_op), "The circuit doesn't match the expected inverse QFT circuit"

    # Edge case: n=0 (should raise an error or return an empty circuit)
    try:
        candidate_circ = candidate(0)
        assert candidate_circ.num_qubits == 0, "For n=0, circuit should have 0 qubits"
    except Exception:
        pass  # Allow exception if function correctly handles invalid input

check(qft_inverse)
Generate Qiskit code that sets up a StagedPassManager with a trivial layout using PassManager for the least busy backend available.
You must implement this using a function named `trivial_layout` with no arguments.

Solution:
from qiskit.transpiler import PassManager, StagedPassManager
from qiskit_ibm_runtime import QiskitRuntimeService
from qiskit.transpiler.passes.layout.trivial_layout import TrivialLayout

def trivial_layout():
    pm_opt = StagedPassManager()
    pm_opt.layout = PassManager()
    backend = QiskitRuntimeService().least_busy()
    cm = backend.coupling_map
    pm_opt.layout += TrivialLayout(cm)
    return pm_opt


Test:
from qiskit.transpiler import PassManager, StagedPassManager
from qiskit_ibm_runtime import QiskitRuntimeService
from qiskit.transpiler.passes.layout.trivial_layout import TrivialLayout
def check(candidate):
    from qiskit.transpiler import PassManager, StagedPassManager
    from qiskit.transpiler.passes.layout.trivial_layout import TrivialLayout
    from qiskit_ibm_runtime import QiskitRuntimeService

    # Run the candidate function
    pm_opt = candidate()

    # Check if the result is a StagedPassManager
    assert isinstance(pm_opt, StagedPassManager), "Output should be a StagedPassManager"

    # Check if the layout attribute exists and is an instance of PassManager
    assert hasattr(pm_opt, "layout"), "pm_opt should have a layout attribute"
    assert isinstance(pm_opt.layout, PassManager), "layout should be an instance of PassManager"

    # Ensure the first task in layout uses TrivialLayout
    assert len(pm_opt.layout._tasks) > 0, "PassManager should have tasks"
    assert isinstance(pm_opt.layout._tasks[0][0], TrivialLayout), "First task should be a TrivialLayout"

    # Verify backend is retrieved
    service = QiskitRuntimeService()
    backend = service.least_busy()
    assert backend is not None, "A valid backend should be retrieved"

    # Ensure coupling map is used in the layout
    cm = backend.coupling_map
    assert cm is not None, "Coupling map should be retrieved from the backend"

check(trivial_layout)
Add a multi-controlled-Y operation to qubit 4, controlled by qubits 0-3.
You must implement this using a function named `mcy` with the following arguments: qc.

Solution:
from qiskit import QuantumCircuit
from qiskit.circuit.library import YGate

def mcy(qc):
    mcy_gate = YGate().control(num_ctrl_qubits=4)
    qc.append(mcy_gate, range(5))
    return qc


Test:
from qiskit import QuantumCircuit
from qiskit.circuit.library import YGate
from qiskit.quantum_info import Operator

def check(candidate):
    expected = QuantumCircuit(6)
    expected.h([0, 4, 5])
    mcy_gate = YGate().control(num_ctrl_qubits=4)
    expected.append(mcy_gate, range(5))

    solution = QuantumCircuit(6)
    solution.h([0, 4, 5])
    solution = candidate(solution)
    assert Operator(solution) == Operator(expected)

check(mcy)
Add SWAPs to route `qc` for the `backend` object's coupling map, but don't transform any gates.
You must implement this using a function named `swap_map` with the following arguments: qc, backend.

Solution:
from qiskit import QuantumCircuit
from qiskit.transpiler.passes import BasicSwap
from qiskit.converters import circuit_to_dag, dag_to_circuit
from qiskit_ibm_runtime import IBMBackend

def swap_map(qc, backend):
    swap_pass = BasicSwap(coupling_map=backend.coupling_map)
    dag = circuit_to_dag(qc)
    mapped_dag = swap_pass.run(dag)
    return dag_to_circuit(mapped_dag)


Test:
from qiskit import QuantumCircuit
from qiskit.transpiler.passes import BasicSwap
from qiskit.converters import circuit_to_dag, dag_to_circuit
from qiskit_ibm_runtime import IBMBackend
def check(candidate):
    from qiskit_ibm_runtime.fake_provider import FakeKyiv
    from qiskit.circuit.random import random_circuit
    from qiskit.transpiler.passes import CheckMap
    backend = FakeKyiv()
    for _ in range(3):
        qc = random_circuit(5,5)
        original_ops = qc.count_ops()
        original_ops.pop("swap", None)

        mapped_qc = candidate(qc, backend)

        check_map = CheckMap(coupling_map=backend.coupling_map)
        dag = circuit_to_dag(mapped_qc)
        check_map.run(dag)
        assert check_map.property_set["is_swap_mapped"]

        mapped_ops = mapped_qc.count_ops()
        mapped_ops.pop("swap", None)

        # We convert to set for comparison to ignore dictionary ordering
        assert set(original_ops.items()) == set(mapped_ops.items())

check(swap_map)
Return the most common result as a string of `1`s and `0`s.
You must implement this using a function named `most_common_result` with the following arguments: bits.

Solution:
from statistics import mode
from qiskit.primitives import BitArray

def most_common_result(bits):
    return mode(bits.get_bitstrings())


Test:
from statistics import mode
from qiskit.primitives import BitArray
def check(candidate):
    test_inputs = [
        {"001": 50, "101": 3},
        {"1": 1},
        {"01101": 302, "10010": 10, "101": 209},
    ]
    for counts in test_inputs:
        bit_array = BitArray.from_counts(counts)
        expected = max(counts.items(), key=lambda x: x[1])[0]
        assert candidate(bit_array) == expected

check(most_common_result)
Add a sub-circuit to the quantum circuit `qc` that applies a series of operations for `n` iterations using the `for_loop`.

In each iteration `i`, perform the following:
1. Apply a `RY` rotation on qubit 0 with an angle of `pi/n * i`.
2. Apply a Hadamard gate to qubit 0 and a CNOT gate between qubits 0 and 1 to create a phi plus Bell state.
3. Measure qubit 0 and store the result in the corresponding classical register.
4. Break the loop if the classical register for qubit 0 measures the value 1.

Use the `for_loop` control flow structure to implement the loop and include conditional breaking based on the measurement.
You must implement this using a function named `for_loop_circuit` with the following arguments: qc, n.

Solution:
from qiskit import QuantumCircuit
from numpy import pi

def for_loop_circuit(qc, n):
    with qc.for_loop(range(n)) as i:
        qc.ry(pi/n*i, 0)
        qc.h(0)
        qc.cx(0, 1)
        qc.measure(0, 0)
        with qc.if_test((qc.clbits[0], 1)):
            qc.break_loop()
    return qc


Test:
from qiskit import QuantumCircuit
from numpy import pi
def check(candidate):
    from qiskit.circuit.library import RYGate, HGate, CXGate, Measure
    from qiskit.circuit.controlflow import IfElseOp
    from qiskit.circuit import CircuitInstruction

    qc = QuantumCircuit(2,1)
    solution = candidate(qc, 2)
    
    assert len(solution.data) > 0, "Circuit should have operations added"
    
    op = solution.data[0].operation

    assert op.name == "for_loop"
    assert op.num_qubits == 2 and op.num_clbits == 1
    indexset, loop_param, sub_qc = op.params
    assert indexset == range(2)
    
    # Test sub circuit
    data = sub_qc.data
    qr = qc.qregs[0]
    cr = qc.cregs[0]
    assert data[0] == CircuitInstruction(RYGate(pi/2*loop_param), [qr[0]], [])
    assert data[1] == CircuitInstruction(HGate(), [qr[0]], [])
    assert data[2] == CircuitInstruction(CXGate(), [qr[0], qr[1]], [])
    assert data[3] == CircuitInstruction(Measure(), [qr[0]],[cr[0]])
    assert isinstance(data[4].operation, IfElseOp)
    assert set(data[4].qubits) == {qr[0], qr[1]} or set(data[4].qubits) == {qr[1], qr[0]}
    assert [bit._index for bit in data[4].clbits] == [0]

check(for_loop_circuit)