Skip to content

Getting Started

Abdulkadir Özcan edited this page Mar 26, 2026 · 3 revisions

Getting Started

Installation

pip install pyhsds

Requires Python 3.8+. No mandatory dependencies beyond the standard library.

For development (running tests, linting):

git clone [https://github.com/AutoPyloter/hsds.git](https://github.com/AutoPyloter/hsds.git)
cd hsds
pip install -r requirements-dev.txt
pip install -e .

Your first optimization in 5 minutes

Step 1 — Define the design space

from hsds import DesignSpace, Continuous, Integer

space = DesignSpace()
space.add("x", Continuous(-5.0, 5.0))
space.add("y", Continuous(-5.0, 5.0))
space.add("n", Integer(1, 10))

Step 2 — Write the objective function

The objective receives a harmony dict and must return (fitness, penalty).

  • fitness — the value to minimize (or maximize)
  • penalty — constraint violation amount; ≤ 0 means feasible
def objective(harmony):
    x, y, n = harmony["x"], harmony["y"], harmony["n"]
    fitness = x**2 + y**2 + n * 0.1
    penalty = max(0.0, x + y - 3.0)   # constraint: x + y <= 3
    return fitness, penalty

Step 3 — Run the optimizer

from hsds import Minimization

result = Minimization(space, objective).optimize(
    memory_size = 20,
    max_iter    = 3000,
)

print(result.best_harmony)
# {'x': -0.002, 'y': 0.001, 'n': 1}

print(result.best_fitness)
# 0.1003

print(result.best_penalty)
# 0.0  (feasible)

Reading the result

result.best_harmony      # dict of best variable values found
result.best_fitness      # float — best objective value
result.best_penalty      # float — ≤ 0 means fully feasible
result.iterations        # int — number of improvisation steps run
result.elapsed_seconds   # float — wall clock time
result.history           # list of (fitness, penalty) per iteration

Dependent variable bounds

Variable bounds can depend on previously assigned variables in the same harmony. This is HSDS's most powerful feature.

space = DesignSpace()
space.add("h",  Continuous(0.30, 1.20))        # beam height
space.add("b",  Continuous(
    lo = lambda ctx: ctx["h"] * 0.3,           # b >= 0.3h
    hi = lambda ctx: ctx["h"] * 0.7,           # b <= 0.7h
))
space.add("As", Continuous(
    lo = lambda ctx: 0.003 * ctx["b"] * ctx["h"],   # min steel
    hi = lambda ctx: 0.025 * ctx["b"] * ctx["h"],   # max steel
))

Variables are sampled in definition order. Each variable's bounds are resolved using the values already assigned.


Engineering variables

For structural engineering problems, use the built-in domain spaces:

from hsds import ACIRebar, SteelSection, ConcreteGrade

# ACI 318 reinforcement (checks ductility, spacing, min/max steel ratio)
space.add("rebar", ACIRebar(d_expr=0.55, cc_expr=60.0, fc=30.0, fy=420.0))

# Standard steel I-section from built-in catalog
space.add("section", SteelSection(series=["IPE"]))

# EN 206 concrete grade
space.add("grade", ConcreteGrade(min_grade="C25/30", max_grade="C50/60"))

See Engineering Spaces for full documentation.


Crash recovery for long runs

result = Minimization(space, objective).optimize(
    max_iter         = 100_000,
    checkpoint_path  = "my_run.json",
    checkpoint_every = 1000,
    resume           = "auto",       # continue if file exists
)

If the process is interrupted, re-run the same line and it continues from where it left off.


Next steps

Clone this wiki locally