Skip to content

Design goals and principles

This page records the durable product and architectural principles for HeuristicLib. It describes why the library is designed as it is and should outlive the current implementation.

HeuristicLib is in early alpha. Public APIs may change when a materially stronger design is identified and backward compatibility is not yet a design goal.

For implementation rules, public API conventions and contributor decisions, see Developer guidelines. Repository workflow and validation commands live in AGENTS.md.

North star

HeuristicLib should become a modern library first toolkit for heuristic optimization that is:

  • predictable
  • composable
  • testable
  • easy to embed
  • easy to use correctly

This implies:

  • no GUI assumptions
  • plain C# composition over framework magic
  • explicit execution control and integration points
  • a small number of strong concepts instead of many overlapping abstractions

The library should serve researchers and practitioners first while remaining easy to use from notebooks, services, automation and AI driven workflows.

Core principles

Small coherent conceptual model

The public model should revolve around a deliberately small vocabulary such as:

  • problem
  • candidate
  • search space
  • objective
  • algorithm
  • operator
  • run
  • search state
  • execution instance

Prefer one honest concept over parallel hierarchies when their semantics are truly shared.

Pit of success and strong typing

The library should make correct usage natural and incorrect usage difficult.

Static typing, explicit invariants and clear API shapes should prevent mistakes where practical. A user should not need deep framework knowledge to configure and run a standard algorithm.

Explicit dependencies and data flow

Behavior affecting inputs such as randomness, cancellation, time, scheduling and caches should remain explicit.

Avoid ambient state, hidden orchestration and opaque indirection. Execution should be understandable from the configuration and the data passed through it.

Immutable candidate flow

Candidates represent values being searched. Existing candidates should remain stable while operators produce new candidates and search states describe public progress.

This gives algorithms, analysis and concurrent execution a predictable value oriented foundation.

Clear execution and evaluation boundaries

The problem defines canonical evaluation semantics. An explicit evaluator layer may sit between algorithms and problem evaluation when it provides meaningful composition such as caching, repeated evaluation, observation or scheduling.

Problems score candidates by returning objective vectors, and evaluators return objective vectors for the candidates they are given.

Shared operators should support batch oriented APIs when batch context is part of the operation semantics.

Performance as a design constraint

Heuristic optimization invokes the same operator and evaluation paths millions of times in one run. Performance is therefore a first-class constraint on the design itself, not a later optimization pass over a design that ignored it.

Shared machinery should avoid unnecessary allocation, boxing, delegate creation and interface indirection. An expensive operator does not excuse overhead that is material for a lightweight one, because both travel the same path.

This constrains abstractions rather than excusing unclear code. An abstraction whose supporting machinery costs more than the behavior it centralizes should not exist; a readable implementation that has not been shown to cost anything should not be replaced by a clever one.

Where a hot path genuinely needs caller-owned scratch memory, output buffers or caches, express that through overloads or an execution-state object whose ownership and lifetime rules match the surrounding operator or execution model. Do not invent one-off scratch-memory conventions on isolated operators. Immutable candidates may still allocate when a new candidate is the real result; the goal is to avoid the accidental temporaries around that result.

Released under the MIT License.