2323
2424public class FactorialDOE {
2525
26-
27- private static final Logger log = LogManager .getLogger (FactorialDOE .class );
26+ private static final Logger log = LogManager .getLogger ( FactorialDOE .class );
2827
2928 /**
3029 * Generates a full factorial design matrix for a set of design factors.
3130 * <p>
32- * A full factorial design enumerates all possible combinations of discrete levels
33- * for the provided design factors. Each row in the resulting matrix corresponds
34- * to one combination of factor levels, and each column corresponds to a design factor.
35- * This method is useful in design of experiments (DOE) where exhaustive sampling
36- * of the factor space is required.
31+ * A full factorial design enumerates all possible combinations of discrete levels for the provided design factors. Each row in the
32+ * resulting matrix corresponds to one combination of factor levels, and each column corresponds to a design factor. This method is
33+ * useful in design of experiments (DOE) where exhaustive sampling of the factor space is required.
3734 * <p>
38- * The input is an integer array where each element represents the number of discrete
39- * levels for a corresponding design factor.
35+ * The input is an integer array where each element represents the number of discrete levels for a corresponding design factor.
4036 * <p>
4137 * Example:
4238 * <pre>
@@ -58,36 +54,106 @@ public class FactorialDOE {
5854 * {1.0,2.0,5.0}}
5955 * </pre>
6056 * <p>
61- * Notes:
62- * - Number of rows = product of all input factor levels.
63- * - Number of columns = number of design factors.
64- * - Values are zero-indexed, representing the level number for each factor.
65- * - This method only generates the combinations; it does not perform optimization.
57+ * Notes: - Number of rows = product of all input factor levels. - Number of columns = number of design factors. - Values are
58+ * zero-indexed, representing the level number for each factor. - This method only generates the combinations; it does not perform
59+ * optimization.
6660 *
67- * @param designFactorLevelArray an array where each element specifies the number of levels for a design factor
61+ * @param designFactorLevelArray
62+ * an array where each element specifies the number of levels for a design factor
6863 */
69- public static RealMatrix FullFactorial ( int [] designFactorLevelArray ) {
64+ public static RealMatrix fullFactorial ( int [] designFactorLevelArray ) {
7065 // calculate matrix size by number of combinations
7166 int length = designFactorLevelArray .length ;
7267 int combinationCount = 1 ;
73- for (int i = 0 ; i < length ; i ++) {
74- combinationCount *= designFactorLevelArray [i ];
68+ for ( int i = 0 ; i < length ; i ++ ) {
69+ combinationCount *= designFactorLevelArray [ i ];
7570 }
76- log .debug ("Total Combinations: " + combinationCount );
71+ log .debug ( "Total Combinations: " + combinationCount );
7772 // create matrix for storing combinations
7873 Array2DRowRealMatrix matrixFactory = new Array2DRowRealMatrix ();
79- RealMatrix matrix = matrixFactory .createMatrix (combinationCount , length );
74+ RealMatrix matrix = matrixFactory .createMatrix ( combinationCount , length );
8075
8176 // populate matrix
82- for (int rowNum = 0 ; rowNum < combinationCount ; rowNum ++) {
77+ for ( int rowNum = 0 ; rowNum < combinationCount ; rowNum ++ ) {
8378 int temp = rowNum ;
84- for (int colNum = 0 ; colNum < designFactorLevelArray .length ; colNum ++) {
85- matrix .setEntry (rowNum , colNum , temp % designFactorLevelArray [colNum ] );
86- temp /= designFactorLevelArray [colNum ];
79+ for ( int colNum = 0 ; colNum < designFactorLevelArray .length ; colNum ++ ) {
80+ matrix .setEntry ( rowNum , colNum , temp % designFactorLevelArray [ colNum ] );
81+ temp /= designFactorLevelArray [ colNum ];
8782 }
8883 }
89- log .debug (matrix .toString ());
84+ log .debug ( matrix .toString () );
9085 return matrix ;
9186 }
9287
88+ /**
89+ * Generates a full factorial design matrix for 2-level design factors.
90+ * <p>
91+ * This method creates a design matrix where each factor has exactly two levels: -1 and +1. It's commonly used in screening experiments
92+ * and fractional factorial designs.
93+ * <p>
94+ * The resulting matrix will have 2^k rows (where k is the number of factors) and k columns. Each row represents a unique combination of
95+ * factor levels.
96+ * <p>
97+ * Example usage:
98+ * <pre>
99+ * {@code
100+ * RealMatrix design = FactorialDOE.fullFactorial2Level(3);
101+ * // Generates an 8x3 matrix with all combinations of -1 and +1
102+ * }
103+ * </pre>
104+ * <p>
105+ * Sample output for 2 factors:
106+ * <pre>
107+ * {{-1.0, -1.0},
108+ * { 1.0, -1.0},
109+ * {-1.0, 1.0},
110+ * { 1.0, 1.0}}
111+ * </pre>
112+ *
113+ * @param designFactorCount
114+ * the number of 2-level design factors
115+ *
116+ * @return a RealMatrix containing all possible combinations of factor levels
117+ *
118+ * @throws IllegalArgumentException
119+ * if designFactorCount is negative
120+ */
121+ public static RealMatrix fullFactorial2Level ( int designFactorCount ) {
122+ // create matrix
123+ Integer combinationCount = ( int ) Math .pow ( 2 , designFactorCount );
124+ Array2DRowRealMatrix matrixFactory = new Array2DRowRealMatrix ();
125+ RealMatrix matrix = matrixFactory .createMatrix ( combinationCount , designFactorCount );
126+ log .debug ( "Total Combinations: " + combinationCount );
127+ // populate matrix
128+ // Generate all binary numbers from 0 to (2^k - 1)
129+ for ( int i = 0 ; i < combinationCount ; i ++ ) {
130+ // For each factor/column
131+ for ( int j = 0 ; j < designFactorCount ; j ++ ) {
132+ // Check the (k-j-1)-th bit from right
133+ // If bit is 0 → -1, if bit is 1 → 1
134+ int bitPosition = designFactorCount - j - 1 ;
135+ int bitValue = ( i >> bitPosition ) & 1 ;
136+ matrix .setEntry ( i , j , bitValue == 0 ? -1 : 1 );
137+ }
138+ }
139+ log .debug ( matrix .toString () );
140+ return matrix ;
141+ }
142+
143+ public static void fractionalFactorial ( String generetor ) {
144+ // validate generetor string
145+ if ( !generetor .matches ( "^[A-Za-z +\\ -]+$" ) ) {
146+ throw new IllegalArgumentException ( "Generator string contains invalid characters. Allowed: letters, space, +, -" );
147+ }
148+ int factorCount = 0 ;
149+ for ( int i = 0 ; i < generetor .length () - 1 ; i ++ ) {
150+ if ( generetor .contains ( " " ) ) {
151+ factorCount += 1 ;
152+ }
153+ }
154+ if ( generetor .split ( " " ).length != factorCount ) {
155+ throw new IllegalArgumentException ( "Generator does not match the number of factors" );
156+ }
157+ }
158+
93159}
0 commit comments