LunaBench: Expert

LunaBench supplies algorithms for solving and executing QUBOs/Qiskit Circuits, but also allows for the integration of personalized custom algorithms to assess performance compared to other solving algorithms. These custom algorithms operate locally, ensuring intellectual property remains confidential and is not shared with third parties.

Integrating custom algorithms

LunaBench enables the integration of custom algorithms through the @solver decorator. By appending this decorator to the solve function, the dataset can be processed using the custom algorithm. It is also necessary to assign an identifier to the algorithm for accurate result allocation by LunaBench, as demonstrated: @solver(algorithm_id="YOUR_ALGORITHM").

For LunaBench to successfully process the dataset without encountering errors, the solve/minimize function must include the input argument qubo (as a list of lists or 2D numpy array), circuit (as string or QuantumCircuit) or lp (as string).

Additionally, the function's output must be structured as a dictionary containing at least the following key-value pairs:

  • "solution" refers to the binary solution vector, presented in list format
  • "energy" denotes the solution value, commonly expressed as f(x) = xᵀQx (None, if not applicable)
  • "runtime" indicates the duration taken by the algorithm to derive the solution
import time
import numpy as np

from lunabench import solver

# use the decorator @solver to define your custom algorithm
@solver(algorithm_id="random")
def random_solve(qubo):
    # log the runtime
    start_time = time.time()

    # get a random solution
    np_solution = np.random.randint(2, size=len(qubo))

    end_time = time.time()
    solve_time = end_time - start_time

    # calculate the energy
    energy = float((np_solution.T @ qubo @ np_solution))
    solution = np_solution.tolist()

    # return a dict containing "solution", "energy" and "runtime"
    result = {"solution": solution, "energy": energy, "runtime": solve_time}

    return result

Solving the dataset

After personalizing the algorithm to address specific problem instances with the appropriate input and output formats, it is possible to utilize the solve_dataset function of LunaBench in the same manner as demonstrated in the section "Beginner". This process requires only the addition of the corresponding algorithm name to the solve_algorithms list/dictionary.

from lunabench import solve_dataset

# specify the algorithms
algorithms = ["sa", "random"]

# define the problem type
problem_name = "bpsp"

# define the dataset
dataset = {
    "id_00": {"sequence": [1, 2, 0, 1, 2, 0]},
    "id_01": {"sequence": [1, 0, 0, 1, 2, 2]},
    "id_02": {"sequence": [0, 1, 0, 1, 2, 2]},
}

# define the number of runs for each algorithm
n_runs = 2

# solve the complete dataset
solved, result_id = solve_dataset(
    problem_name=problem_name,
    dataset=dataset,
    solve_algorithms=algorithms,
    n_runs=n_runs,
)

Adding custom metrics

Comparable to the custom algorithm, the @metric decorator enables the specification of a custom metric for the evaluation phase of LunaBench. It is necessary to supply a metric name using @metric(metric_id="YOUR_METRIC") to ensure correct assignment of the output in the result data by LunaBench.

The input arguments for the custom metric must be named in accordance with the corresponding column names in solution.csv (see section "Beginner").

from lunabench import metric

# use the decorator @metric to define your custom metric
@metric(metric_id="n_cars")
def count_cars(sequence, best_solution):
    # compute the number of total cars
    if 2 * len(best_solution) == len(sequence):
        return len(sequence)
    return 2 * len(best_solution)

Evaluating the results

As before, the metric name can be included in the metrics_config to evaluate the solutions or results using the custom metric.

from lunabench import evaluate_results

# define the metrics
metrics = ["n_cars"]

# run the evaluation
eval_data, plot_outs = evaluate_results(result_id=result_id, dataset=dataset, metrics_config=metrics)

This section marks the conclusion of the comprehensive tutorial dedicated to exploring the functionalities and capabilities of LunaBench. To remain informed about the latest updates or to access further information, individuals are encouraged to stay engaged.

Was this page helpful?