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