Skip to content

Features

Overview

Features are components that extract model-level properties from optimization models. Unlike solvers or metrics, features run once per model in the model set, not once per solver-model combination. Capturing that kind of intrinsic, model-level structure — problem size, constraint matrix density, objective function characteristics — is exactly their job.

Features subclass BaseFeature and are registered with the @feature decorator — both from luna_bench.custom. Each feature implements a single method:

Python
def run(self, model: Model) -> FeatureResult

The decorator automatically sets the class variable registered_id: ClassVar[str], which serves as the unique identifier for the feature within a benchmark.


Built-in Features

Luna Bench ships with three categories of built-in features: general features that apply to any model, MIP features for research-grade structural analysis of mixed-integer programming models, and QUBO features for structural analysis of Quadratic Unconstrained Binary Optimization models.

General Features

Feature Description
VarNumberFeature Extracts the number of variables in a model. A basic structural property, useful as a proxy for problem size. Module: luna_bench.features.var_num_feature.
OptSolFeature Extracts the optimal solution value from a model. Commonly used as a reference point when evaluating solver performance or computing optimality gaps. Module: luna_bench.features.optsol_feature.

MIP Features (Research-Grade)

All MIP features reside under the luna_bench.features.mip/ package. These features perform deeper structural analysis of mixed-integer programming models and are intended for research and advanced benchmarking workflows.

Feature Description
ProblemSizeFeatures Captures core problem dimensions including the number of variables, constraints, and non-zero entries in the model. These values provide a first-order characterization of instance difficulty. Module: luna_bench.features.mip.problem_size_feature.
LinearConstraintMatrixFeatures Analyzes structural properties of the constraint matrix, such as density, sparsity patterns, and related linear-algebraic characteristics. Module: luna_bench.features.mip.linear_constraint_matrix.
ObjectiveFunctionFeature Extracts characteristics of the objective function, including coefficient distributions and other properties relevant to solver behavior. Module: luna_bench.features.mip.objective_function_features.
RightHandSideFeatures Computes properties of the right-hand side (RHS) vector, capturing the distribution and structure of constraint bounds. Module: luna_bench.features.mip.right_hand_side_feature.
VariableConstraintGraphFeatures Analyzes the topology of the bipartite graph formed between variables and constraints. Graph-based features can reveal clustering, connectivity, and other structural patterns that influence solver performance. Module: luna_bench.features.mip.variable_constraint_graph_feature.

QUBO Features

All QUBO features reside under the luna_bench.features.qubo/ package. These features perform structural analysis of Quadratic Unconstrained Binary Optimization (QUBO) models by examining properties of the QUBO matrix, its interaction graph, and its spectral decomposition.

Feature Description
QuboGraphFeature Computes graph-theoretic features from the QUBO matrix by interpreting it as a weighted adjacency matrix and constructing a graph via NetworkX. Covers connectivity (average degree distribution, average clustering coefficient, number of connected components, average path length) and robustness (graph density, number of bridges, number of articulation points). An optional include_self_loops parameter controls whether diagonal entries are included as self-loops or zeroed out before analysis. Module: luna_bench.features.qubo.graph_features.
QuboMatrixFeature Computes descriptive statistics over all entries of the QUBO matrix: central tendency and dispersion (mean, median, variance, standard deviation, min, max), distribution shape (skewness and kurtosis of the flattened matrix), and quantiles (10th and 90th percentiles and the coefficient of variation). Module: luna_bench.features.qubo.matrix_features.
QuboSparsityDensityFeature Computes structural features describing the fill pattern of the QUBO matrix. Includes the sparsity and density ratios, the counts of zero and non-zero entries, and the number of variables (matrix dimension). Module: luna_bench.features.qubo.sparsity_density_features.
QuboSpectralAnalysisFeature Decomposes the QUBO matrix using symmetric eigendecomposition (numpy.linalg.eigh) and computes descriptive statistics over eigenvalues and eigenvector components (mean, median, standard deviation, coefficient of variation, 10th and 90th percentiles, min, max, and the dominant eigenvalue). Additionally reports the condition number (ratio of largest to smallest singular value) as an indicator of numerical stability. Module: luna_bench.features.qubo.spectral_analysis_features.

Writing Custom Features

You can write a custom feature as a class or as a plain function. The class form returns a typed FeatureResult; the function form returns a plain dict that is wrapped for you. The two paths differ, so pick a tab and follow its steps:

Write the Function

Decorate a function that takes a Model and returns a dict (or a FeatureResult); a dict is wrapped automatically, so there is no separate result type to define. The @feature decorator still registers it and sets registered_id for you:

Python
from luna_quantum import Model
from luna_bench.custom import feature

@feature
def my_feature(model: Model) -> dict:
    return {"my_value": 42.0}

Define a Result Type

Feature results inherit from FeatureResult. Each field becomes a named data point associated with the model:

Python
from luna_bench.custom import FeatureResult

class MyFeatureResult(FeatureResult):
    my_value: float

Implement the Feature

Subclass BaseFeature, implement run, and apply the @feature decorator. It registers the class and sets registered_id automatically — you do not set it manually:

Python
from luna_quantum import Model
from luna_bench.custom import BaseFeature, feature

@feature
class MyFeature(BaseFeature[MyFeatureResult]):
    def run(self, model: Model) -> MyFeatureResult:
        return MyFeatureResult(my_value=42.0)

Feature Results

All feature results inherit from FeatureResult. There are two common patterns for structuring return values.

Numeric / Scalar Results

The most straightforward pattern is to define one or more numeric fields on your result class:

Python
class SizeResult(FeatureResult):
    num_variables: int
    num_constraints: int

Enum-Based Results

For categorical data, features can return enum-based results using the EnumFeatureResult pattern. This is useful when a feature classifies a model into discrete categories rather than producing a numeric value. For example, a feature might classify a model's constraint matrix as "sparse", "moderate", or "dense" instead of returning a raw density value.

Python
from enum import Enum
from luna_bench.custom import FeatureResult

class DensityCategory(Enum):
    SPARSE = "sparse"
    MODERATE = "moderate"
    DENSE = "dense"

class DensityResult(FeatureResult):
    category: DensityCategory

Enum-based results integrate with downstream analysis and reporting just as numeric results do, but they signal to consumers that the value is categorical.


Adding Features to a Benchmark

Once a feature is defined, register it with a benchmark instance using add_feature. The first argument is a string identifier, and the second is an instance of your feature class.

Python
bench.add_feature("my-feature", MyFeature())

You can register multiple features on the same benchmark:

Python
from luna_bench.features import VarNumberFeature, OptSolFeature

bench.add_feature("var-count", VarNumberFeature())
bench.add_feature("optimal-solution", OptSolFeature())
bench.add_feature("my-feature", MyFeature())

Each feature runs independently against every model in the model set. The results are collected and made available for downstream metrics, analysis, and reporting.