PyDFLT

class DFLDataset(data_dict: dict[str, ndarray | Tensor])

DFLDataset class extends PyTorch’s Dataset for decision-focused learning (DFL) scenarios.

It manages a dictionary of data (data_dict) where keys represent different quantities (e.g., ‘features’, ‘costs’, ‘weights’, ‘optimal_decision’) and values are torch.Tensors. The class ensures that all data tensors have the same number of samples (first dimension) and are at least 2D. It provides methods to access data by index and to add new data.

data_dict

The core dictionary holding all dataset components. Keys are strings identifying the data type (e.g., ‘features’, ‘costs’), and values are torch.Tensors. All tensors are guaranteed to have the same number of samples in their first dimension and are at least 2D.

Type:

dict[str, torch.Tensor]

keys

A list of keys currently present in data_dict.

Type:

list[str]

num_samples

The number of samples in the dataset, determined from the first dimension of the tensors in data_dict.

Type:

int

Methods

add_data(key, data)

Adds new data component(s) to the dataset.

class Logger(experiment_name: str, project_name: str, config: dict[str, Any] | None = None, use_wandb: bool = True, experiments_folder: str = 'results/', main_metric: str = 'abs_regret', store_min_and_max: bool = True)

A comprehensive logging class for machine learning experiments, integrating with Weights & Biases and managing local log files. It aggregates per-batch results into epoch-level metrics. See src.utils for method load_log for loading logs.

experiment_name

The name of the current experiment.

Type:

str

project_name

The name of the project.

Type:

str

config

Configuration dictionary for WandB.

Type:

dict[str, Any] | None

path_to_log

The Path object pointing to the directory where logs are stored.

Type:

Path

log_file_path

The Path object pointing to the text log file.

Type:

Path

store_min_and_max

Flag indicating whether to store min and max for metrics.

Type:

bool

use_wandb

Flag indicating whether Weights & Biases is being used.

Type:

bool

epoch_metrics_list

A list storing dictionaries of aggregated metrics for each epoch.

Type:

list[dict[str, float]]

logging_keys

A set of all metric keys encountered across epochs.

Type:

set[str]

main_metric

The name of the main metric used for returning values from log_epoch_results.

Type:

str

Methods

finish()

Finishes the Weights & Biases run if it was initialized.

log_epoch_results(per_batch_results, epoch_num)

Receives a list of dictionaries with per-batch results, aggregates them, and logs.

printout()

Utility function that prints out the aggregated epoch results to the console.

class Noisifier(base_predictor: Predictor, bias: bool = True, sigma_setting: str = 'independent', sigma_init: float | ndarray = 1, sigma_final: float = 0.1, total_steps_cooling: int = 100, cooling_type: str = 'linear', log_normal: bool = False)

A class that adds noise to the output of a base predictor.

The Noisifier can operate in several modes for determining the standard deviation (sigma) of the noise: - “fixed”: Sigma is a fixed value. - “cooling”: Sigma anneals from an initial to a final value over a set number of steps. - “dependent”: Sigma is predicted by a linear layer based on the input. - “independent”: Sigma is a learnable parameter, independent of the input.

It can model the output as a Normal or LogNormal distribution. If the base_predictor is an MLPNormalPredictor, it can model both the mean and standard deviation of the underlying Normal distribution with noise.

Methods

add_module(name, module)

Add a child module to the current module.

apply(fn)

Apply fn recursively to every submodule (as returned by .children()) as well as self.

bfloat16()

Casts all floating point parameters and buffers to bfloat16 datatype.

buffers([recurse])

Return an iterator over module buffers.

children()

Return an iterator over immediate children modules.

compile(*args, **kwargs)

Compile this Module's forward using torch.compile().

cpu()

Move all model parameters and buffers to the CPU.

cuda([device])

Move all model parameters and buffers to the GPU.

double()

Casts all floating point parameters and buffers to double datatype.

eval()

Set the module in evaluation mode.

extra_repr()

Return the extra representation of the module.

float()

Casts all floating point parameters and buffers to float datatype.

forward(x)

Performs a forward pass, returning the mean prediction from the base predictor.

forward_dist(x[, eps])

Performs a forward pass and returns a distribution object representing the noisy output.

get_buffer(target)

Return the buffer given by target if it exists, otherwise throw an error.

get_extra_state()

Return any extra state to include in the module's state_dict.

get_parameter(target)

Return the parameter given by target if it exists, otherwise throw an error.

get_sigma(x)

Calculates and returns the current sigma based on the setting.

get_submodule(target)

Return the submodule given by target if it exists, otherwise throw an error.

half()

Casts all floating point parameters and buffers to half datatype.

ipu([device])

Move all model parameters and buffers to the IPU.

load_state_dict(state_dict[, strict, assign])

Copy parameters and buffers from state_dict into this module and its descendants.

modules()

Return an iterator over all modules in the network.

mtia([device])

Move all model parameters and buffers to the MTIA.

named_buffers([prefix, recurse, ...])

Return an iterator over module buffers, yielding both the name of the buffer as well as the buffer itself.

named_children()

Return an iterator over immediate children modules, yielding both the name of the module as well as the module itself.

named_modules([memo, prefix, remove_duplicate])

Return an iterator over all modules in the network, yielding both the name of the module as well as the module itself.

named_parameters([prefix, recurse, ...])

Return an iterator over module parameters, yielding both the name of the parameter as well as the parameter itself.

output_to_dist(output)

Converts the direct output of the Noisifier (which is the mean prediction) into a distribution, primarily for compatibility with interfaces expecting a distribution from the base predictor's output format.

parameters([recurse])

Return an iterator over module parameters.

register_backward_hook(hook)

Register a backward hook on the module.

register_buffer(name, tensor[, persistent])

Add a buffer to the module.

register_forward_hook(hook, *[, prepend, ...])

Register a forward hook on the module.

register_forward_pre_hook(hook, *[, ...])

Register a forward pre-hook on the module.

register_full_backward_hook(hook[, prepend])

Register a backward hook on the module.

register_full_backward_pre_hook(hook[, prepend])

Register a backward pre-hook on the module.

register_load_state_dict_post_hook(hook)

Register a post-hook to be run after module's load_state_dict() is called.

register_load_state_dict_pre_hook(hook)

Register a pre-hook to be run before module's load_state_dict() is called.

register_module(name, module)

Alias for add_module().

register_parameter(name, param)

Add a parameter to the module.

register_state_dict_post_hook(hook)

Register a post-hook for the state_dict() method.

register_state_dict_pre_hook(hook)

Register a pre-hook for the state_dict() method.

requires_grad_([requires_grad])

Change if autograd should record operations on parameters in this module.

set_extra_state(state)

Set extra state contained in the loaded state_dict.

set_submodule(target, module[, strict])

Set the submodule given by target if it exists, otherwise throw an error.

share_memory()

See torch.Tensor.share_memory_().

state_dict(*args[, destination, prefix, ...])

Return a dictionary containing references to the whole state of the module.

to(device)

Moves and/or casts the parameters and buffers.

to_empty(*, device[, recurse])

Move the parameters and buffers to the specified device without copying storage.

train([mode])

Set the module in training mode.

type(dst_type)

Casts all parameters and buffers to dst_type.

update_t(new_t)

Updates the current step t for sigma cooling.

xpu([device])

Move all model parameters and buffers to the XPU.

zero_grad([set_to_none])

Reset gradients of all model parameters.

__call__

class Problem(data_dict: dict[str, ndarray], opt_model: OptimizationModel, train_ratio: float = 0.7, val_ratio: float = 0.15, compute_optimal_decisions: bool = True, compute_optimal_objectives: bool = True, standardize_features: bool = False, time_respecting_split: bool = False, knn_robust_loss: int = 0, knn_robust_loss_weight: float = 0.0, seed: int | None = None, verbose: bool = True)

Manages a decision-focused learning (DFL) problem encapsulating the dataset (DFLDataset) and an optimization model (OptimizationModel). It is responsible for:

  • Splitting the data into training, validation, and test sets.

  • Standardizing features if specified.

  • Computing optimal decisions and objectives for the dataset instances, potentially using a k-NN robust approach if configured.

  • Providing an interface to access data batches for different modes (train/val/test).

  • Delegating solving, objective calculation, and evaluation tasks to the OptimizationModel.

mode

The current operational mode of the problem instance (e.g., ‘train’, ‘validation’, ‘test’).

Type:

Optional[str]

train_indices

Indices for the training dataset.

Type:

Optional[np.ndarray]

validation_indices

Indices for the validation dataset.

Type:

Optional[np.ndarray]

test_indices

Indices for the test dataset.

Type:

Optional[np.ndarray]

opt_model

The optimization model associated with the problem.

Type:

OptimizationModel

num_vars

Number of decision variables in the optimization model.

Type:

int

num_features

Number of features in the input data.

Type:

int

params_to_predict_shapes

Shapes of the parameters to be predicted by a machine learning model, as defined in opt_model.

Type:

Dict[str, Tuple]

num_predictions

Total number of scalar values to be predicted, derived from params_to_predict_shapes.

Type:

int

dataset

The dataset object holding all problem instances.

Type:

DFLDataset

train_ratio

Proportion of the dataset to use for training.

Type:

float

val_ratio

Proportion of the dataset to use for validation.

Type:

float

compute_optimal_decisions

If True, computes and stores the optimal decisions for each instance in the dataset. Defaults to True.

Type:

bool, optional

time_respecting_split

Whether to perform a time-respecting split (no shuffling before splitting).

Type:

bool

knn_robust_loss

If greater than 0, enables k-NN robust loss computation for the training set, using this value as the number of neighbours ‘k’. This involves finding k-nearest neighbors to perturb parameters for robust decision-making. Defaults to 0 (disabled).

Type:

int, optional

mode_to_indices

A dictionary mapping mode strings (‘train’, ‘validation’, ‘test’) to their corresponding data indices.

Type:

dict[str, np.ndarray]

total_num_samples

Total number of samples in the dataset.

Type:

int

all_indices

An array of all indices from 0 to num_samples-1.

Type:

np.ndarray

train_size

Number of samples in the training set.

Type:

int

validation_size

Number of samples in the validation set.

Type:

int

test_size

Number of samples in the test set.

Type:

int

Attributes

mode

test_indices

train_indices

validation_indices

Methods

evaluate(data_batch, decisions_batch[, ...])

Evaluates various performance metrics for a batch, given true data, decisions, and optionally, predicted parameters.

generate_batch_indices(batch_size)

Generates a list of index arrays (batches) for the currently set mode.

get_objective(data_batch, decisions_batch[, ...])

Calculates the objective value for a batch, given the true data, decisions, and optionally, predicted parameters.

read_data(idx)

Retrieves data from the dataset for the specified indices.

set_mode(mode)

Sets the current operational mode of the Problem instance.

solve(data_batch)

Solves the optimization problem for a given batch of data.

split_dataset([seed])

Splits the dataset indices into training, validation, and test sets.

class Runner(decision_maker: DecisionMaker, num_epochs: int = 3, experiments_folder: str = 'results/', main_metric: str = 'abs_regret', val_metrics: list[str] | None = None, test_metrics: list[str] | None = None, store_min_and_max: bool = False, use_wandb: bool = False, experiment_name: str = '-', project_name: str = '-', early_stop: bool = False, min_delta_early_stop: float | None = None, patience_early_stop: float | None = None, save_best: bool = True, seed: int | None = None, full_reproducibility_GPUs: bool = False, config: dict[str, Any] | None = None, verbose: bool = True)

The Runner class allows for running experiments. It uses the given DecisionMaker to run the experiments with and initializes a Logger to log results. It handles the training and evaluation process, including logging, early stopping, and saving the best models found so far.

decision_maker

The decision maker instance to be trained and evaluated.

Type:

DecisionMaker

num_epochs

The total number of epochs for training.

Type:

int

config

A dictionary containing experiment configurations to be logged.

Type:

dict[str, Any] | None

experiments_folder

The root directory where experiment results will be saved.

Type:

str

use_wandb

Flag indicating if Weights & Biases logging is enabled.

Type:

bool

experiment_name

Name of the current experiment.

Type:

str

project_name

Name of the project for logging purposes.

Type:

str

early_stop

Flag indicating if early stopping is enabled.

Type:

bool

min_delta_early_stop

Minimum change in the main metric to be considered an improvement for early stopping.

Type:

float | None

patience_early_stop

Number of epochs to wait for an improvement before stopping early.

Type:

float | None

save_best

Flag indicating if the best performing model should be saved.

Type:

bool

main_metric

The primary metric used for model selection and early stopping.

Type:

str

store_min_and_max

Whether to store min and max values of metrics in the logger.

Type:

bool

verbose

If True, print status messages to the console.

Type:

bool

main_metric_sense

Direction of optimisation for the main metric, either ‘MIN’ or ‘MAX’.

Type:

str

no_improvement_count

Counter for epochs without significant improvement, used for early stopping.

Type:

int

best_val_metric

Stores the best validation metric value achieved so far.

Type:

float

logger

The logger instance used for recording experiment results.

Type:

Logger

Methods

run([optuna_trial])

Runs the experiment.

class DecisionMaker(problem: Problem, learning_rate: float = 1e-4, device_str: str = 'cpu', predictor_str: str = 'MLP', decision_model_str: str = 'base', loss_function_str: str = 'objective', to_decision_pars: str = 'none', use_dist_at_mode: str = 'none', use_noisifier: bool = False, standardize_predictions: bool = True, init_OLS: bool = False, seed: int | None = None, predictor_kwargs: dict | None = None, noisifier_kwargs: dict | None = None, decision_model_kwargs: dict | None = None)

Abstract base class for a decision-making agent in a decision-focused learning pipeline.

This class orchestrates the interaction between a predictive model (predictor), an optional noisifier to add stochasticity to predictions, and a decision_model (an optimization model) to make decisions based on (potentially noisy) predictions. It handles the initialization of these components, the process of predicting parameters and making decisions, and provides hooks for training and evaluation.

The class is organized into several categories of methods: - Abstract methods for subclass implementation: Need to be implemented for a subclass to work. - Core logic methods: Methods that include the core logic of what a decision maker entails - Helper methods: Local methods that support other methods - Conversion methods: Methods that convert, i.e., transform or reshape certain objects. - Initialization methods: Methods that do initialization

problem

The problem instance containing data and the true optimization model.

Type:

Problem

learning_rate

Learning rate for the trainable components.

Type:

float

device

The device (CPU or GPU) on which computations are performed.

Type:

torch.device

predictor_str

String identifier for the type of predictor used.

Type:

str

decision_model_str

String identifier for the type of decision model used.

Type:

str

loss_function_str

String identifier for the loss function.

Type:

str

to_decision_pars

Strategy for converting distributional predictions to deterministic parameters for the decision model (e.g., ‘sample’, ‘quantiles’).

Type:

str

use_dist_at_mode

Specifies if/when to use full distributional output from predictor/noisifier (e.g., ‘test’ mode).

Type:

str

use_noisifier

Flag indicating whether a noisifier is used on top of the base predictor.

Type:

bool

standardize_predictions

Flag indicating whether to standardize predictions.

Type:

bool

predictor_kwargs

Keyword arguments for predictor initialization.

Type:

dict[str, Any]

noisifier_kwargs

Keyword arguments for noisifier initialization.

Type:

dict[str, Any]

decision_model_kwargs

Keyword arguments for decision model initialization.

Type:

dict[str, Any]

decision_model

The instantiated optimization model used for making decisions.

Type:

OptimizationModel

predictor

The instantiated predictive model.

Type:

Predictor

best_predictor

A copy of the predictor with the best validation performance.

Type:

Predictor | None

noisifier

The instantiated noisifier, if use_noisifier is True.

Type:

Noisifier | None

trainable_predictive_model

The PyTorch module that is trained (either the predictor or the noisifier if used).

Type:

nn.Module

num_scenarios

Number of scenarios used if to_decision_pars involves sampling or quantiles, derived from decision_model_kwargs.

Type:

int | None

_solver_calls

Counter for the number of times the decision model’s solver is called.

Type:

int

_epoch_counts

Counter for the number of epochs run (though not explicitly updated in this snippet).

Type:

int

Attributes

best_predictor

Methods

decide(predictions_batch)

Makes decisions using the self.decision_model based on the provided predictions.

dict_to_decisions(decisions_batch[, use_optimal])

Reverts a dictionary of named parameter predictions back into a single flat tensor.

dict_to_predictions(predictions_batch)

Reverts a dictionary of named parameter predictions back into a single flat tensor.

dict_to_tensor(predictions_dict[, output_device])

Converts a dictionary of tensors to a single tensor by concatenating them.

predict(data_batch[, output_device])

Generates predictions for a given data batch.

predict_and_decide(data_batch)

Performs a prediction step followed by a decision-making step.

predictions_to_dict(predictions[, output_device])

Converts a flat tensor of predictions into a dictionary.

run_epoch(mode, epoch_num[, metrics])

Runs one full epoch of operations (training, validation, or testing).

save_best_predictor()

Saves a deep copy of the current self.predictor to self.best_predictor.

update(data_batch)

Performs a single training update step for the learnable components.

class Predictor(num_inputs: int, num_outputs: int, num_scenarios: int = 1)

Base class for all predictors. Predictors are restricted to be instances of torch.nn.Module.

num_inputs

The number of inputs for the predictor.

Type:

int

num_outputs

The total number of outputs the predictor produces. If num_scenarios > 1, this is the total output (output_per_scenario * num_scenarios).

Type:

int

num_scenarios

The number of scenarios the predictor is designed to handle. If 1, the predictor outputs a single prediction. If > 1, the predictor outputs multiple predictions (one per scenario).

Type:

int

Methods

add_module(name, module)

Add a child module to the current module.

apply(fn)

Apply fn recursively to every submodule (as returned by .children()) as well as self.

bfloat16()

Casts all floating point parameters and buffers to bfloat16 datatype.

buffers([recurse])

Return an iterator over module buffers.

children()

Return an iterator over immediate children modules.

compile(*args, **kwargs)

Compile this Module's forward using torch.compile().

cpu()

Move all model parameters and buffers to the CPU.

cuda([device])

Move all model parameters and buffers to the GPU.

double()

Casts all floating point parameters and buffers to double datatype.

eval()

Set the module in evaluation mode.

extra_repr()

Return the extra representation of the module.

float()

Casts all floating point parameters and buffers to float datatype.

forward(x)

Abstract method for the forward pass of the predictor.

forward_mean(x)

Computes the mean of the predictor's output across scenarios.

get_buffer(target)

Return the buffer given by target if it exists, otherwise throw an error.

get_extra_state()

Return any extra state to include in the module's state_dict.

get_parameter(target)

Return the parameter given by target if it exists, otherwise throw an error.

get_submodule(target)

Return the submodule given by target if it exists, otherwise throw an error.

half()

Casts all floating point parameters and buffers to half datatype.

ipu([device])

Move all model parameters and buffers to the IPU.

load_state_dict(state_dict[, strict, assign])

Copy parameters and buffers from state_dict into this module and its descendants.

modules()

Return an iterator over all modules in the network.

mtia([device])

Move all model parameters and buffers to the MTIA.

named_buffers([prefix, recurse, ...])

Return an iterator over module buffers, yielding both the name of the buffer as well as the buffer itself.

named_children()

Return an iterator over immediate children modules, yielding both the name of the module as well as the module itself.

named_modules([memo, prefix, remove_duplicate])

Return an iterator over all modules in the network, yielding both the name of the module as well as the module itself.

named_parameters([prefix, recurse, ...])

Return an iterator over module parameters, yielding both the name of the parameter as well as the parameter itself.

parameters([recurse])

Return an iterator over module parameters.

register_backward_hook(hook)

Register a backward hook on the module.

register_buffer(name, tensor[, persistent])

Add a buffer to the module.

register_forward_hook(hook, *[, prepend, ...])

Register a forward hook on the module.

register_forward_pre_hook(hook, *[, ...])

Register a forward pre-hook on the module.

register_full_backward_hook(hook[, prepend])

Register a backward hook on the module.

register_full_backward_pre_hook(hook[, prepend])

Register a backward pre-hook on the module.

register_load_state_dict_post_hook(hook)

Register a post-hook to be run after module's load_state_dict() is called.

register_load_state_dict_pre_hook(hook)

Register a pre-hook to be run before module's load_state_dict() is called.

register_module(name, module)

Alias for add_module().

register_parameter(name, param)

Add a parameter to the module.

register_state_dict_post_hook(hook)

Register a post-hook for the state_dict() method.

register_state_dict_pre_hook(hook)

Register a pre-hook for the state_dict() method.

requires_grad_([requires_grad])

Change if autograd should record operations on parameters in this module.

set_extra_state(state)

Set extra state contained in the loaded state_dict.

set_submodule(target, module[, strict])

Set the submodule given by target if it exists, otherwise throw an error.

share_memory()

See torch.Tensor.share_memory_().

state_dict(*args[, destination, prefix, ...])

Return a dictionary containing references to the whole state of the module.

to(*args, **kwargs)

Move and/or cast the parameters and buffers.

to_empty(*, device[, recurse])

Move the parameters and buffers to the specified device without copying storage.

train([mode])

Set the module in training mode.

type(dst_type)

Casts all parameters and buffers to dst_type.

xpu([device])

Move all model parameters and buffers to the XPU.

zero_grad([set_to_none])

Reset gradients of all model parameters.

__call__