Skip to content

Commit ee64ee2

Browse files
Create effects.py
1 parent aa6516f commit ee64ee2

1 file changed

Lines changed: 68 additions & 0 deletions

File tree

src/spotpython/effects.py

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
import numpy as np
2+
3+
def random_orientation(k: int, p: int, xi: float) -> np.ndarray:
4+
"""
5+
Generates a random orientation matrix for a screening design based on the Morris method.
6+
Translated from the original MATLAB function randorient.m.
7+
8+
This function creates a (k+1) x k matrix that specifies a random path through the design space.
9+
Each element in the path is at a distance Delta = xi/(p-1) from one level to the next on a p-level grid.
10+
11+
Args:
12+
k (int):
13+
Number of design variables.
14+
p (int):
15+
Number of discrete levels along each dimension.
16+
xi (float):
17+
Elementary effect step length factor.
18+
19+
Returns:
20+
np.ndarray:
21+
A (k+1) x k matrix (Bstar) representing the randomized orientation.
22+
23+
Examples:
24+
>>> import numpy as np
25+
>>> Bstar = random_orientation(k=3, p=4, xi=1.0)
26+
>>> print(Bstar)
27+
"""
28+
# Step length
29+
Delta = xi / (p - 1)
30+
31+
# Number of rows in the resulting orientation matrix
32+
m = k + 1
33+
34+
# Create a truncated p-level grid in one dimension
35+
# up to (1 - Delta) in steps of 1/(p-1)
36+
step = 1.0 / (p - 1)
37+
xs = np.arange(0, 1.0 - Delta + step / 2, step)
38+
xsl = len(xs)
39+
40+
# Build the basic sampling matrix B
41+
# Shape: (k+1, k)
42+
top_row = np.zeros((1, k))
43+
lower_tri = np.tril(np.ones((k, k)))
44+
B = np.vstack([top_row, lower_tri])
45+
46+
# Matrix Dstar with +1 or -1 on the diagonal
47+
sign_vals = 2 * np.round(np.random.rand(k)) - 1
48+
Dstar = np.diag(sign_vals)
49+
50+
# Random base value xstar for each column
51+
rand_indices = np.floor(np.random.rand(k) * xsl).astype(int)
52+
xstar = xs[rand_indices]
53+
54+
# Permutation matrix Pstar of dimension k x k
55+
Pstar = np.zeros((k, k))
56+
perm = np.random.permutation(k)
57+
for i in range(k):
58+
Pstar[i, perm[i]] = 1
59+
60+
# Construct the orientation matrix
61+
# (ones(m,1)*xstar) builds the base, then we add the randomized increments
62+
# and multiply with Pstar for column permutation
63+
ones_m_k = np.ones((m, k))
64+
partial_matrix = (2 * B - ones_m_k) @ Dstar + ones_m_k
65+
B_star = np.outer(np.ones(m), xstar) + (Delta / 2.0) * partial_matrix
66+
B_star = B_star @ Pstar
67+
68+
return B_star

0 commit comments

Comments
 (0)