Design Principles ================= This page summarizes the architectural choices that shape Asunder's package layout and public APIs. Layered Package Structure ------------------------- Asunder is intentionally split into layers: - ``asunder`` is the public facade - ``asunder.base`` contains reusable building blocks - ``asunder.load_balancing`` contains the load-balanced graph partitioning application layer - ``asunder.nlbnp`` contains the nonlinear branch-and-price application layer This split exists to keep reusable code reusable. The base layer should remain general enough to support additional applications without inheriting application-specific assumptions from the load balancing or NLBNP workflows. Prefer Reusable Placement ------------------------- When new functionality is added, the default question should be: "Could this be reused by another application package?" If the answer is yes, the code should usually live in ``asunder.base``. If the answer is no, or if the code is tightly bound to one workflow or one case-study family, it should live in ``asunder.load_balancing``, ``asunder.nlbnp``, or in a future peer application package. That principle is why: - branch-and-price infrastructure lives in ``asunder.base.branch_and_price`` - reusable decomposition machinery lives in ``asunder.base.column_generation`` - load balancing master, partition generation, and refinement logic lives in ``asunder.load_balancing`` - NLBNP-specific refinement logic lives in ``asunder.nlbnp.algorithms`` - ``modular_very_fortunate_descent`` remains in ``asunder.base.algorithms`` Keep the Top Level Thin ----------------------- Top-level ``asunder`` should expose the most useful entry points, but it should not become a second full package tree. Its job is to provide convenient imports for orchestration and common workflows, not to duplicate the canonical module layout. Graph-First Interfaces ---------------------- The package is designed around graph-derived interfaces: - adjacency or weight matrices - partition matrices - pairwise constraints such as must-link, cannot-link, and worthy edges This keeps the reusable core compact and allows different application areas to share the same decomposition machinery even when the original optimization models differ substantially. Composable Extension Points --------------------------- Asunder is meant to be extended by swapping or supplementing a few key pieces: - initial feasible column generation - master problem logic - subproblem or pricing logic - refinement logic This is preferable to encoding a large number of hard-wired workflow variants in the core package. The package should make customization straightforward without forcing every application into a single monolithic path. Optional Dependency Boundaries ------------------------------ Some algorithms and workflows rely on optional dependencies such as igraph, leidenalg, plotting libraries, or solver backends. The package design favors graceful optionality where possible: - reusable modules should not pull in heavyweight dependencies unnecessarily - documentation should make optional requirements visible - tests should reflect which behavior depends on which extras Documentation Mirrors the Public Surface ---------------------------------------- The Sphinx API docs are intentionally aligned to the package structure. That means the docs are part of the architecture, not an afterthought. When public modules move, the API tree under ``docs/api`` must move with them. The docs should help users understand both the facade and the canonical module paths. Stability Through Explicitness ------------------------------ Asunder favors explicit contracts over hidden conventions. Public callables should have clear inputs and outputs, typed result containers should describe what the orchestration layer returns, and application-specific assumptions should be visible in the module layout rather than hidden inside a generic namespace.