MISDA is a graph-theoretic method for reducing the objectives of a multi-objective problem while retaining original, interpretable variables. The current supported workflow is the refactored static pipeline.
MISDA reports three deliberately distinct quantities:
- latent dimension: independence number of the signed dependence graph
G±, where significant positive and negative dependencies both form edges; - structural dimension: independence number of the positive-redundancy
graph
G+; - preferred MIS size: number of original objectives selected in the highest-ranked maximal independent set.
Connected-component counts remain graph-topology diagnostics and are not used as dimensional estimates. Negative associations connect latent dependence but never create redundancy edges in the structural graph. Constant objectives remain explicit isolated vertices.
git clone https://github.com/monacofj/misda.git
cd misda
python -m pip install .MISDA requires Python 3.8 or newer and depends on NumPy, pandas, SciPy, NetworkX, Matplotlib, and scikit-learn.
import pandas as pd
import misda
frame = pd.read_csv("my_mop_data.csv")
result = misda.analyze(
frame,
aggressiveness=0.5,
max_evaluated_mis=3,
seed=123,
name="Demo",
)
print(result.summary())
print(result.best_mis.objectives)
print(result.best_mis.evaluation["linear_reconstruction"])
figure = result.graph_plot(show=False)analyze() always stores every ranked MIS. Light evaluation — external linear
reconstruction, delete-one uncertainty, and Pareto preservation — is attached
to the requested ranked prefix. Use max_evaluated_mis to limit that work.
The result tree separates global analysis, candidates, and reproducibility:
result.analysis.structural_dimension
result.analysis.latent_dimension
result.selected_dimension
result.analysis.separation_status
result.mis
result.execution.configuration
result.execution.timings
result.execution.convergenceFor synthetic or empirical cases with an external declaration, compare the
completed analysis without passing that declaration into analyze():
truth = {
"name": "Demo benchmark",
"latent_expected": 2,
"structural_expected": 3,
"blocks_expected": [["f1", "f2"], ["f3"], ["f4", "f5"]],
"pareto_expected": [0, 4, 9],
"feature": "Known synthetic structure.",
"intuition": "One representative per structural block.",
"graph_expected": "Three disjoint positive components.",
}
bench = misda.benchmark(result, truth)
print(bench.report())Analysis values remain in bench.result; only comparisons requiring the
external declaration are stored directly in bench.
The current method estimates structural_dimension as the independence number
of the positive graph G+ and latent_dimension as the independence number of
the signed dependence graph G±. The number of connected components of each
graph is stored separately as topology. The selected dimension remains
result.selected_dimension, the size of the preferred MIS. benchmark()
compares each declared dimension with its corresponding estimate; it never
substitutes the selected dimension for either estimate.
Nonlinear reconstruction is intentionally opt-in. Select candidates by their
position in result.mis:
misda.heavy(result, [0, 2], null_reference=True)
print(result.report())The heavy path uses nested leave-one-out Random Forest evaluation, internal
model selection, data-driven tree stopping, and an optional sequential null
reference. It mutates the selected candidates in place and records convergence,
uncertainty, seed, and timing. A callable cancel_requested may be supplied by
interactive applications.
The executable benchmark modules are the source of truth; the notebooks are thin front ends over the same functions.
python -m examples.benchmarks.run_benchmark --output results/benchmark.json
python -m examples.benchmarks.run_comparative --output results/comparative.jsonThe comparative artifact keeps PCA global standardized reconstruction R² separate from MISDA reconstruction of eliminated objectives. They describe different estimands and are not merged into a single score.
The supported and acceptance-tested path is misda.analyze(..., method="static"), which is also the default. Transitional aliases such as
caution, result.plot(), result.alpha_min, and result.mis_sets emit
DeprecationWarning; use aggressiveness, graph_plot(), the analysis tree,
and result.mis instead.
The earlier adaptive implementation remains suspended for compatibility work. It is not part of the current scientific baseline, documentation contract, or test acceptance gate.
See the user guide for the complete result schema, evaluation semantics, migration notes, and limitations. See design notes for the statistical and architectural rationale.
See docs/CONTRIBUTING.md.
Souza, C. H., Monaco, F. J., Delbem, A. C. B., and Kuruvilla, J. A. Maximal Independent Structural Dimensionality Analysis (in print), 2026.