Analyzing qubo solutions
QUBOAnalyzer example
To analyze the solutions from one or many QUBO solvers, we can instantiate a QUBOAnalyzer
with solutions and labels as follows:
import torch
from qubosolver.data import QUBOSolution
from qubosolver.qubo_analyzer import QUBOAnalyzer
num_bitstrings=100
bit_length=3
costs = torch.randint(1, 20, (2**bit_length,), dtype=torch.float)
bitstrings = torch.randint(0, 2, (num_bitstrings, bit_length))
bitstrings,counts=bitstrings.unique(dim=0,return_counts=True)
solution1 = QUBOSolution(bitstrings, costs, counts)
bitstrings = torch.randint(0, 2, (num_bitstrings, bit_length))
bitstrings,counts=bitstrings.unique(dim=0,return_counts=True)
solution2 = QUBOSolution(bitstrings, costs, counts)
# Create the analyzer with our two solutions
analyzer = QUBOAnalyzer([solution1, solution2], labels=["sol1", "sol2"])
df = analyzer.df
This will generate a pandas dataframe internally (accessible via the df
attribute) for several QUBOAnalyzer
methods for plotting or comparing solutions,
described below. More examples are demonstrated in the QUBOAnalyzer
tutorial.
QUBOAnalyzer API description
QUBOAnalyzer(solutions, labels=None)
Analyzer for solutions to a Quadratic Unconstrained Binary Optimization (QUBO) problem.
Initializes the analyzer with one or a list of QUBOSolutions.
If a single QUBOSolution is provided, it is automatically wrapped into a list. Optionally, you can provide a list of labels corresponding to each QUBOSolution. If labels are not provided, they are assigned automatically as '0', '1', etc.
PARAMETER | DESCRIPTION |
---|---|
solutions
|
A single QUBOSolution or a list of QUBOSolution instances.
TYPE:
|
labels
|
A list of labels for the QUBOSolutions. Must match the number of solutions.
TYPE:
|
RAISES | DESCRIPTION |
---|---|
ValueError
|
If no solutions are provided or if the number of labels does not match the number of solutions. |
TypeError
|
If any solution or label is not of the expected type. |
Source code in qubosolver/qubo_analyzer.py
add_counts(counts)
Updates the DataFrame by adding the counts column.
If counts are provided at a later stage, this method will add the counts to the DataFrame and ensure that they match the number of bitstrings.
PARAMETER | DESCRIPTION |
---|---|
counts
|
A list or tensor of counts.
TYPE:
|
RAISES | DESCRIPTION |
---|---|
ValueError
|
If the length of counts does not match the number of bitstrings. |
Source code in qubosolver/qubo_analyzer.py
add_probs(probs)
Updates the DataFrame by adding the probs column.
If probs are provided at a later stage, this method will add the probs to the DataFrame and ensure that they match the number of bitstrings.
PARAMETER | DESCRIPTION |
---|---|
probs
|
A list or tensor of probabilities.
TYPE:
|
RAISES | DESCRIPTION |
---|---|
ValueError
|
If the length of probabilities does not match the number of bitstrings. |
Source code in qubosolver/qubo_analyzer.py
average_cost(top_percent=1)
Calculates the average cost for the best top_percent of bitstrings (lowest cost) for each solution.
PARAMETER | DESCRIPTION |
---|---|
top_percent
|
A fraction between 0 and 1 representing the percentage of lowest cost bitstrings to consider.
TYPE:
|
RETURNS | DESCRIPTION |
---|---|
DataFrame
|
pd.DataFrame: A DataFrame with each solution label, the average cost over the best top_percent bitstrings, and the count of bitstrings used. |
Source code in qubosolver/qubo_analyzer.py
best_bitstrings()
Finds all unique bitstrings (with the best cost) in each solution's DataFrame.
RETURNS | DESCRIPTION |
---|---|
DataFrame
|
pd.DataFrame: A DataFrame with all unique rows per solution (solution_label) that have the best (lowest) cost. |
Source code in qubosolver/qubo_analyzer.py
bitstrings_to_tensor(bitstring_list)
staticmethod
Converts a list of bitstring strings to a torch tensor of bitstrings.
Each bitstring in the list is assumed to be a string of '0's and '1's (e.g., "010101"). Converts each character to an integer and constructs a tensor of shape (num_bitstrings, bitstring_length).
PARAMETER | DESCRIPTION |
---|---|
bitstring_list
|
A list of bitstring strings.
TYPE:
|
RETURNS | DESCRIPTION |
---|---|
Tensor
|
torch.Tensor: A tensor with shape (num_bitstrings, bitstring_length) with integer elements. |
RAISES | DESCRIPTION |
---|---|
ValueError
|
If the list is empty or if the bitstrings are not of uniform length. |
Source code in qubosolver/qubo_analyzer.py
calculate_costs(Q)
Calculates the cost for each bitstring using the provided Q QUBOInstance.
cost = x^T Q x
The computed cost is added as the columns _COSTS in the DataFrame.
PARAMETER | DESCRIPTION |
---|---|
Q
|
QUBOInstance
TYPE:
|
RETURNS | DESCRIPTION |
---|---|
DataFrame
|
pd.DataFrame: The updated DataFrame including the _COSTS column. |
RAISES | DESCRIPTION |
---|---|
ValueError
|
If a bitstring's length does not match Q.shape[0]. |
Source code in qubosolver/qubo_analyzer.py
calculate_gaps(opt_cost, Q=None)
Calculates the gaps for each bitstring using the provided optimal cost. If costs aren ot present calculates costs as
cost = x^T Q x
The computed cost is added as the columns _COSTS in the DataFrame.
PARAMETER | DESCRIPTION |
---|---|
Q
|
QUBOInstance
TYPE:
|
RETURNS | DESCRIPTION |
---|---|
DataFrame
|
pd.DataFrame: The updated DataFrame including the _COSTS column. |
RAISES | DESCRIPTION |
---|---|
ValueError
|
If a bitstring's length does not match Q.shape[0]. |
Source code in qubosolver/qubo_analyzer.py
compare_qubo_solutions(target_labels)
Compare two QUBOSolution
objects and provide a statistical analysis of the differences,
including degenerate solution matching and mismatch statistics.
PARAMETER | DESCRIPTION |
---|---|
target_labels
|
The labels of the solutions to compare. If None, compares all solutions.
TYPE:
|
Source code in qubosolver/qubo_analyzer.py
filter_by_cost(max_cost, df=None)
Returns a DataFrame limited to bitstrings whose cost is smaller than the provided threshold.
PARAMETER | DESCRIPTION |
---|---|
max_cost
|
Maximum cost threshold.
TYPE:
|
df
|
DataFrame to filter.
TYPE:
|
RETURNS | DESCRIPTION |
---|---|
DataFrame
|
pd.DataFrame: The filtered DataFrame. |
Source code in qubosolver/qubo_analyzer.py
filter_by_percentage(top_percent=1.0, column=_COSTS, order='ascending')
Returns a DataFrame limited to the best bitstrings
in a given column for each solution group,
where "best" means that the cumulative probability (_PROBS)
of the selected rows reaches at least
top_percent. The sorting order is controlled by the
order
parameter: if "ascending", the group is sorted
in ascending order (lower values are considered better);
if "descending", sorted in descending order.
PARAMETER | DESCRIPTION |
---|---|
top_percent
|
A threshold between 0 and 1 representing the fraction of cumulative probability. For example, 0.1 means select bitstrings until their cumulative probability is ≥ 10%.
TYPE:
|
column
|
The key (column) by which to sort the rows (e.g. _COSTS, _GAPS, or _PROBS). Defaults to _COSTS.
TYPE:
|
order
|
Either "ascending" or "descending". If "ascending", rows are sorted in ascending order (lower values are better). If "descending", rows are sorted in descending order (higher values are better).
TYPE:
|
RETURNS | DESCRIPTION |
---|---|
DataFrame
|
pd.DataFrame: The filtered DataFrame containing, for each solution group, the bitstrings whose cumulative probability (_PROBS) reaches the specified top_percent threshold. |
RAISES | DESCRIPTION |
---|---|
ValueError
|
If the specified column is not in the DataFrame, if top_percent is not in (0, 1], or if the order parameter is not "descending" or "ascending". |
Source code in qubosolver/qubo_analyzer.py
filter_by_probability(min_probability, df=None)
Returns a DataFrame limited to bitstrings whose probability is greater than the provided threshold.
PARAMETER | DESCRIPTION |
---|---|
min_probability
|
Minimum probability threshold.
TYPE:
|
df
|
DataFrame to filter.
TYPE:
|
RETURNS | DESCRIPTION |
---|---|
DataFrame
|
pd.DataFrame: The filtered DataFrame. |
RAISES | DESCRIPTION |
---|---|
ValueError
|
If the 'probabilities' column is not present. |
Source code in qubosolver/qubo_analyzer.py
plot(x_axis, y_axis, labels=None, sort_by=None, sort_order='ascending', probability_threshold=None, cost_threshold=None, top_percent=None, context='notebook')
A wrapper function that chooses between plotting costs, counts, or probabilities as a function of bitstrings or as a function of cost.
Source code in qubosolver/qubo_analyzer.py
plot_no_bitstrings(df, x_axis, y_axis, sort_by=None, sort_order='ascending', context='notebook')
staticmethod
Plots a bar chart of probabilities or counts as a function of cost.
PARAMETER | DESCRIPTION |
---|---|
df
|
The DataFrame to plot. Defaults to None, that means uses self.df.
TYPE:
|
x_axis
|
The column name to be plotted on the x-axis.
TYPE:
|
y_axis
|
The column name to be plotted on the y-axis.
TYPE:
|
sort_by
|
Defines the column by which to sort the costs. If None, no sorting is done.
TYPE:
|
sort_order
|
Defines the sorting order. Accepts 'ascending' or 'descending'.
Default is 'ascending'. Ignored if
TYPE:
|
Source code in qubosolver/qubo_analyzer.py
plot_vs_bitstrings(df, y_axis, sort_by=None, sort_order='descending', context='notebook')
staticmethod
Plots a bar chart of costs, counts, or probabilities as a function of bitstrings.
PARAMETER | DESCRIPTION |
---|---|
df
|
The DataFrame to plot. Defaults to None, that means uses self.df.
TYPE:
|
y_axis
|
The column name to be plotted on the y-axis.
TYPE:
|
sort_by
|
Defines the column by which to sort the bitstrings. If None, no sorting is done.
TYPE:
|
sort_order
|
Defines the sorting order. Accepts 'ascending' or 'descending'.
Default is 'ascending'. Ignored if
TYPE:
|
Source code in qubosolver/qubo_analyzer.py
tensor_to_bitstrings(bitstring_tensor)
staticmethod
Converts a torch tensor of bitstrings to a list of bitstring strings.
Each row in the tensor is assumed to be a bitstring (with integer elements 0 or 1), and is converted to a single string (e.g., a row [0, 1, 0, 1, 0, 1] becomes "010101").
PARAMETER | DESCRIPTION |
---|---|
bitstring_tensor
|
Tensor of shape (num_bitstrings, bitstring_length) where each element is an integer (0 or 1).
TYPE:
|
RETURNS | DESCRIPTION |
---|---|
list[str]
|
list[str]: A list of bitstring strings. |