|
2 | 2 | # Email: simon.blanke@yahoo.com |
3 | 3 | # License: MIT License |
4 | 4 |
|
| 5 | +import numpy as np |
| 6 | + |
5 | 7 |
|
6 | 8 | class Direction: |
7 | | - def __init__(self, position_1, position_2) -> None: |
| 9 | + """ |
| 10 | + Represents a search direction for Powell's method. |
| 11 | +
|
| 12 | + This class handles movement along an arbitrary direction vector in the |
| 13 | + search space, supporting line searches for 1D optimization. |
| 14 | + """ |
| 15 | + |
| 16 | + def __init__(self, direction_vector: np.ndarray): |
8 | 17 | """ |
9 | | - Parameters: |
10 | | - - position_1: dict, starting point in the search-space |
11 | | - - position_2: dict, end point in the search-space |
| 18 | + Initialize a direction for line search. |
| 19 | +
|
| 20 | + Parameters |
| 21 | + ---------- |
| 22 | + direction_vector : np.ndarray |
| 23 | + The direction vector to search along. Will be normalized. |
12 | 24 | """ |
| 25 | + norm = np.linalg.norm(direction_vector) |
| 26 | + if norm < 1e-10: |
| 27 | + raise ValueError("Direction vector cannot be zero") |
| 28 | + self.direction = direction_vector / norm |
| 29 | + |
| 30 | + def get_position_at(self, origin: np.ndarray, t: float) -> np.ndarray: |
| 31 | + """ |
| 32 | + Calculate position along the direction from an origin point. |
| 33 | +
|
| 34 | + Parameters |
| 35 | + ---------- |
| 36 | + origin : np.ndarray |
| 37 | + Starting position in search space |
| 38 | + t : float |
| 39 | + Step size along the direction (can be negative) |
13 | 40 |
|
14 | | - self.position_1 = position_1 |
15 | | - self.position_2 = position_2 |
| 41 | + Returns |
| 42 | + ------- |
| 43 | + np.ndarray |
| 44 | + New position: origin + t * direction |
| 45 | + """ |
| 46 | + return origin + t * self.direction |
| 47 | + |
| 48 | + @classmethod |
| 49 | + def from_two_points(cls, position_1: np.ndarray, position_2: np.ndarray): |
| 50 | + """ |
| 51 | + Create a Direction from two points in the search space. |
| 52 | +
|
| 53 | + Parameters |
| 54 | + ---------- |
| 55 | + position_1 : np.ndarray |
| 56 | + Starting point |
| 57 | + position_2 : np.ndarray |
| 58 | + End point |
| 59 | +
|
| 60 | + Returns |
| 61 | + ------- |
| 62 | + Direction |
| 63 | + Direction pointing from position_1 to position_2 |
| 64 | + """ |
| 65 | + direction_vector = position_2 - position_1 |
| 66 | + return cls(direction_vector) |
16 | 67 |
|
17 | | - def get_new_position(self, t): |
| 68 | + @classmethod |
| 69 | + def coordinate_axis(cls, dimension: int, n_dimensions: int): |
18 | 70 | """ |
19 | | - Calculate a position on the line (vector) between two positions using parameter t. |
| 71 | + Create a Direction along a coordinate axis. |
20 | 72 |
|
21 | | - Parameters: |
22 | | - - t: float, parameter indicating the position along the line (0 <= t <= 1 for within the line segment) |
| 73 | + Parameters |
| 74 | + ---------- |
| 75 | + dimension : int |
| 76 | + Which axis (0-indexed) |
| 77 | + n_dimensions : int |
| 78 | + Total number of dimensions |
23 | 79 |
|
24 | | - Returns: |
25 | | - - dict representing the new position in the search-space coordinate system |
| 80 | + Returns |
| 81 | + ------- |
| 82 | + Direction |
| 83 | + Unit vector along the specified axis |
26 | 84 | """ |
27 | | - new_position = {} |
28 | | - for dim in self.position_1: |
29 | | - # Calculate the position along the line in each dimension |
30 | | - new_position[dim] = self.position_1[dim] + t * ( |
31 | | - self.position_2[dim] - self.position_1[dim] |
32 | | - ) |
33 | | - return new_position |
| 85 | + direction_vector = np.zeros(n_dimensions) |
| 86 | + direction_vector[dimension] = 1.0 |
| 87 | + return cls(direction_vector) |
0 commit comments