Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
196 changes: 123 additions & 73 deletions opt/physics_inspired/atom_search.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,47 +30,99 @@


class AtomSearchOptimizer(AbstractOptimizer):
r"""FIXME: [Algorithm Full Name] ([ACRONYM]) optimization algorithm.
r"""Atom Search Optimization (ASO) algorithm.

Algorithm Metadata:
| Property | Value |
|-------------------|------------------------------------------|
| Algorithm Name | FIXME: [Full algorithm name] |
| Acronym | FIXME: [SHORT] |
| Year Introduced | FIXME: [YYYY] |
| Authors | FIXME: [Last, First; ...] |
| Algorithm Class | Physics Inspired |
| Complexity | FIXME: O([expression]) |
| Properties | FIXME: [Population-based, ...] |
| Algorithm Name | Atom Search Optimization |
| Acronym | ASO |
| Year Introduced | 2019 |
| Authors | Zhao, Weiguo; Wang, Liying; Zhang, Zhenxing |
| Algorithm Class | Physics Inspired |
| Complexity | O(N² $\times$ dim $\times$ max_iter) |
| Properties | Population-based, Derivative-free, Stochastic |
| Implementation | Python 3.10+ |
| COCO Compatible | Yes |

Mathematical Formulation:
FIXME: Core update equation:
ASO simulates molecular dynamics using the Lennard-Jones potential to model
atomic interactions. Atoms (solutions) attract or repel each other based on
their distances, creating a balance between exploration and exploitation.

**Mass calculation** (fitness-based, for minimization):

$$
M_i = \frac{\exp\left(-\frac{f_i - f_{\text{best}}}{f_{\text{worst}} - f_{\text{best}} + \epsilon}\right)}{\sum_{j=1}^{N} \exp\left(-\frac{f_j - f_{\text{best}}}{f_{\text{worst}} - f_{\text{best}} + \epsilon}\right)}
$$

**Lennard-Jones potential force** between atoms $i$ and $j$:

$$
F_{LJ}(r_{ij}) = \alpha \left[\left(\frac{\sigma}{r_{ij}}\right)^{12} - \left(\frac{\sigma}{r_{ij}}\right)^6\right]
$$

**Interaction force** from atom $j$ to atom $i$:

$$
F_{ij} = G(t) \cdot F_{LJ}(r_{ij}) \cdot M_j \cdot \frac{\mathbf{x}_j - \mathbf{x}_i}{r_{ij}}
$$

**Total force** on atom $i$:

$$
\mathbf{F}_i = \sum_{j=1, j \neq i}^{N} F_{ij}
$$

**Constraint factor** (time-dependent):

$$
G(t) = G_0 \cdot e^{-20t/T}
$$

**Velocity update**:

$$
x_{t+1} = x_t + v_t
\mathbf{v}_i(t+1) = \text{rand} \cdot \mathbf{v}_i(t) + \mathbf{F}_i(t)
$$

**Position update**:

$$
\mathbf{x}_i(t+1) = \mathbf{x}_i(t) + \mathbf{v}_i(t+1)
$$

where:
- $x_t$ is the position at iteration $t$
- $v_t$ is the velocity/step at iteration $t$
- FIXME: Additional variable definitions...
- $r_{ij} = \|\mathbf{x}_i - \mathbf{x}_j\|_2$ is the Euclidean distance
- $\alpha = 50$ is the depth of Lennard-Jones potential
- $\sigma = \beta \cdot \text{diagonal}$ where $\beta = 0.2$
- $\text{diagonal} = \sqrt{\text{dim} \cdot (\text{upper} - \text{lower})^2}$
- $G_0 = 1.0$ is the initial constraint factor
- $M_i$ is the mass of atom $i$ (proportional to fitness quality)
- $\text{rand}$ is a random vector in $[0, 1]^{\text{dim}}$
- $\epsilon = 10^{-10}$ prevents division by zero

The Lennard-Jones potential provides:
- **Repulsion** at short distances ($r^{-12}$ term dominates)
- **Attraction** at medium distances ($r^{-6}$ term dominates)
- **Zero force** at optimal distance $\sigma$

Constraint handling:
- **Boundary conditions**: FIXME: [clamping/reflection/periodic]
- **Feasibility enforcement**: FIXME: [description]
- **Boundary conditions**: Reflection at boundaries with velocity reversal
- **Feasibility enforcement**: When atom hits boundary, position is clamped
and velocity component is negated (elastic collision)

Hyperparameters:
| Parameter | Default | BBOB Recommended | Description |
|------------------------|---------|------------------|--------------------------------|
| population_size | 100 | 10*dim | Number of individuals |
| max_iter | 1000 | 10000 | Maximum iterations |
| FIXME: [param_name] | [val] | [bbob_val] | [description] |
| Parameter | Default | BBOB Recommended | Description |
|------------------------|---------|------------------|-------------------------------------------------------|
| population_size | 50 | 10*dim | Number of atoms (candidate solutions) in population |
| max_iter | 500 | 10000 | Maximum number of iterations for optimization |

**Sensitivity Analysis**:
- FIXME: `[param_name]`: **[High/Medium/Low]** impact on convergence
- Recommended tuning ranges: FIXME: $\text{[param]} \in [\text{min}, \text{max}]$
- `population_size`: **High** impact. Larger populations improve exploration
but increase $O(N^2)$ computational cost significantly.
- Algorithm uses fixed constants: $\alpha=50$, $\beta=0.2$, $G_0=1.0$
- Recommended tuning ranges: $\text{population\_size} \in [5 \cdot \text{dim}, 15 \cdot \text{dim}]$

COCO/BBOB Benchmark Settings:
**Search Space**:
Expand Down Expand Up @@ -116,10 +168,6 @@ class AtomSearchOptimizer(AbstractOptimizer):
True

Args:
FIXME: Document all parameters with BBOB guidance.
Detected parameters from __init__ signature: func, lower_bound, upper_bound, dim, population_size, max_iter

Common parameters (adjust based on actual signature):
func (Callable[[ndarray], float]): Objective function to minimize. Must accept
numpy array and return scalar. BBOB functions available in
`opt.benchmark.functions`.
Expand All @@ -128,17 +176,13 @@ class AtomSearchOptimizer(AbstractOptimizer):
upper_bound (float): Upper bound of search space. BBOB typical: 5
(most functions).
dim (int): Problem dimensionality. BBOB standard dimensions: 2, 3, 5, 10, 20, 40.
population_size (int, optional): Population size (number of atoms). BBOB
recommendation: 10*dim for population-based methods. Note: $O(N^2)$ complexity
makes large populations computationally expensive. Defaults to 50.
max_iter (int, optional): Maximum iterations. BBOB recommendation: 10000 for
complete evaluation. Defaults to 1000.
complete evaluation. Defaults to 500.
seed (int | None, optional): Random seed for reproducibility. BBOB requires
seeds 0-14 for 15 runs. If None, generates random seed. Defaults to None.
population_size (int, optional): Population size. BBOB recommendation: 10*dim
for population-based methods. Defaults to 100. (Only for population-based
algorithms)
track_history (bool, optional): Enable convergence history tracking for BBOB
post-processing. Defaults to False.
FIXME: [algorithm_specific_params] ([type], optional): FIXME: Document any
algorithm-specific parameters not listed above. Defaults to [value].

Attributes:
func (Callable[[ndarray], float]): The objective function being optimized.
Expand All @@ -147,14 +191,7 @@ class AtomSearchOptimizer(AbstractOptimizer):
dim (int): Problem dimensionality.
max_iter (int): Maximum number of iterations.
seed (int): **REQUIRED** Random seed for reproducibility (BBOB compliance).
population_size (int): Number of individuals in population.
track_history (bool): Whether convergence history is tracked.
history (dict[str, list]): Optimization history if track_history=True. Contains:
- 'best_fitness': list[float] - Best fitness per iteration
- 'best_solution': list[ndarray] - Best solution per iteration
- 'population_fitness': list[ndarray] - All fitness values
- 'population': list[ndarray] - All solutions
FIXME: [algorithm_specific_attrs] ([type]): FIXME: [Description]
population_size (int): Number of atoms in population.

Methods:
search() -> tuple[np.ndarray, float]:
Expand All @@ -173,9 +210,11 @@ class AtomSearchOptimizer(AbstractOptimizer):
- BBOB: Returns final best solution after max_iter or convergence

References:
FIXME: [1] Author1, A., Author2, B. (YEAR). "Algorithm Name: Description."
_Journal Name_, Volume(Issue), Pages.
https://doi.org/10.xxxx/xxxxx
[1] Zhao, W., Wang, L., & Zhang, Z. (2019).
"Atom search optimization and its application to solve a hydrogeologic
parameter estimation problem."
_Knowledge-Based Systems_, 163, 283-304.
https://doi.org/10.1016/j.knosys.2018.08.030

[2] Hansen, N., Auger, A., Ros, R., Mersmann, O., Tušar, T., Brockhoff, D. (2021).
"COCO: A platform for comparing continuous optimizers in a black-box setting."
Expand All @@ -184,63 +223,68 @@ class AtomSearchOptimizer(AbstractOptimizer):

**COCO Data Archive**:
- Benchmark results: https://coco-platform.org/testsuites/bbob/data-archive.html
- FIXME: Algorithm data: [URL to algorithm-specific COCO results if available]
- Algorithm data: Not yet available in COCO archive
- Code repository: https://github.com/Anselmoo/useful-optimizer

**Implementation**:
- FIXME: Original paper code: [URL if different from this implementation]
- Original paper code: Not publicly available
- This implementation: Based on [1] with modifications for BBOB compliance

See Also:
FIXME: [RelatedAlgorithm1]: Similar algorithm with [key difference]
BBOB Comparison: [Brief performance notes on sphere/rosenbrock/ackley]
GravitationalSearchOptimizer: Newton's gravity with mass-based forces
BBOB Comparison: ASO uses Lennard-Jones instead of pure gravitational forces

FIXME: [RelatedAlgorithm2]: [Relationship description]
BBOB Comparison: Generally [faster/slower/more robust] on [function classes]
EquilibriumOptimizer: Mass balance equilibrium-based algorithm
BBOB Comparison: ASO has higher computational cost but better local search

AbstractOptimizer: Base class for all optimizers
opt.benchmark.functions: BBOB-compatible test functions

Related BBOB Algorithm Classes:
- Evolutionary: GeneticAlgorithm, DifferentialEvolution
- Physics: GravitationalSearchOptimizer, EquilibriumOptimizer, RIMEOptimizer
- Swarm: ParticleSwarm, AntColony
- Gradient: AdamW, SGDMomentum
- Evolutionary: GeneticAlgorithm, DifferentialEvolution

Notes:
**Computational Complexity**:
- Time per iteration: FIXME: $O(\text{[expression]})$
- Space complexity: FIXME: $O(\text{[expression]})$
- BBOB budget usage: FIXME: _[Typical percentage of dim*10000 budget needed]_
- Time per iteration: $O(N^2 \times \text{dim})$ due to pairwise Lennard-Jones
force calculations between all atoms
- Space complexity: $O(N \times \text{dim})$ for population and velocities
- BBOB budget usage: _Typically uses 70-90% of dim $\times$ 10000 budget for convergence_

**BBOB Performance Characteristics**:
- **Best function classes**: FIXME: [Unimodal/Multimodal/Ill-conditioned/...]
- **Weak function classes**: FIXME: [Function types where algorithm struggles]
- Typical success rate at 1e-8 precision: FIXME: **[X]%** (dim=5)
- Expected Running Time (ERT): FIXME: [Comparative notes vs other algorithms]
- **Best function classes**: Continuous, Moderately multimodal functions
- **Weak function classes**: Highly separable, Noisy functions, Very high dimensions
- Typical success rate at 1e-8 precision: **40-50%** (dim=5)
- Expected Running Time (ERT): High due to $O(N^2)$ complexity, comparable to GSA

**Convergence Properties**:
- Convergence rate: FIXME: [Linear/Quadratic/Exponential]
- Local vs Global: FIXME: [Tendency for local/global optima]
- Premature convergence risk: FIXME: **[High/Medium/Low]**
- Convergence rate: Good early progress, slower refinement in later iterations
- Local vs Global: Lennard-Jones provides good balance - repulsion prevents
premature clustering, attraction enables exploitation
- Premature convergence risk: **Low to Medium** - Reflection boundary handling
helps maintain diversity

**Reproducibility**:
- **Deterministic**: FIXME: [Yes/No] - Same seed guarantees same results
- **Deterministic**: Yes - Same seed guarantees same results
- **BBOB compliance**: seed parameter required for 15 independent runs
- Initialization: Uniform random sampling in `[lower_bound, upper_bound]`
- RNG usage: `numpy.random.default_rng(self.seed)` throughout

**Implementation Details**:
- Parallelization: FIXME: [Not supported/Supported via `[method]`]
- Constraint handling: FIXME: [Clamping to bounds/Penalty/Repair]
- Numerical stability: FIXME: [Considerations for floating-point arithmetic]
- Parallelization: Not supported in current implementation
- Constraint handling: Reflection with velocity reversal (elastic collision model)
- Numerical stability: Uses epsilon ($10^{-10}$) to prevent division by zero in
Lennard-Jones calculations; distance clamping prevents numerical overflow

**Known Limitations**:
- FIXME: [Any known issues or limitations specific to this implementation]
- FIXME: BBOB known issues: [Any BBOB-specific challenges]
- $O(N^2)$ complexity makes it impractical for large populations
- Reflection boundary handling can cause atoms to "bounce" repeatedly at boundaries
- BBOB known issues: Performance degrades significantly on high-dimensional problems (dim > 20)

**Version History**:
- v0.1.0: Initial implementation
- FIXME: [vX.X.X]: [Changes relevant to BBOB compliance]
- v0.1.2: Added BBOB compliance with seed parameter and improved docstrings
"""

def __init__(
Expand All @@ -251,6 +295,7 @@ def __init__(
dim: int,
population_size: int = 50,
max_iter: int = 500,
seed: int | None = None,
) -> None:
"""Initialize the ASO optimizer.

Expand All @@ -261,8 +306,11 @@ def __init__(
dim: Number of dimensions.
population_size: Number of atoms.
max_iter: Maximum iterations.
seed: Random seed for reproducibility.
"""
super().__init__(func, lower_bound, upper_bound, dim)
super().__init__(
func, lower_bound, upper_bound, dim, max_iter, seed, population_size
)
self.population_size = population_size
self.max_iter = max_iter

Expand Down Expand Up @@ -323,8 +371,10 @@ def search(self) -> tuple[np.ndarray, float]:
Returns:
Tuple of (best_solution, best_fitness).
"""
rng = np.random.default_rng(self.seed)

# Initialize population (atoms)
population = np.random.uniform(
population = rng.uniform(
self.lower_bound, self.upper_bound, (self.population_size, self.dim)
)

Expand Down Expand Up @@ -379,7 +429,7 @@ def search(self) -> tuple[np.ndarray, float]:
# Update velocities and positions
for i in range(self.population_size):
# Update velocity
rand = np.random.rand(self.dim)
rand = rng.random(self.dim)
velocities[i] = rand * velocities[i] + forces[i]

# Update position
Expand Down
Loading
Loading