Skip to content

Commit 9b26a7a

Browse files
author
nofa
committed
fractional factorial optimization
1 parent 56d340d commit 9b26a7a

3 files changed

Lines changed: 90 additions & 29 deletions

File tree

pom.xml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@
1212

1313
<properties>
1414
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
15+
<maven.compiler.source>17</maven.compiler.source>
16+
<maven.compiler.target>17</maven.compiler.target>
1517
</properties>
1618

1719
<dependencies>

src/main/java/com/jdoe/Testing.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ public static void main( String[] args )
1414
int[] arrayOfLevels = {2,3,6};
1515
// FactorialDOE.fullFactorial(arrayOfLevels);
1616
// FactorialDOE.fullFactorial2Level( arrayOfLevels.length );
17-
FactorialDOE.fractionalFactorial( "a b ab" );
17+
FactorialDOE.fractionalFactorial( "a b -ab" );
18+
FactorialDOE.fractionalFactorial( "a b +ab" );
1819
}
1920
}

src/main/java/com/jdoe/algorithms/FactorialDOE.java

Lines changed: 86 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -146,7 +146,66 @@ public static RealMatrix fullFactorial2Level( int designFactorCount ) {
146146
return matrix;
147147
}
148148

149-
public static void fractionalFactorial( String generetor ) {
149+
/**
150+
* Generates a fractional factorial design matrix from a generator string.
151+
*
152+
* <p>
153+
* This method creates a design matrix for a fractional factorial experiment based on a user-provided generator string.
154+
* The generator string defines main factors and combination factors, optionally with a leading '+' or '-' sign for
155+
* combination factors. Each main factor is treated as a 2-level factor (-1 and +1). Combination factors are computed
156+
* as the row-wise product of the relevant main factor columns, with signs applied if specified.
157+
* </p>
158+
*
159+
* <p>
160+
* The resulting matrix includes:
161+
* <ul>
162+
* <li>Main factor columns: each column corresponds to a main factor, populated using a 2-level full factorial design.</li>
163+
* <li>Combination factor columns: each column is calculated by multiplying the main factor columns involved in that combination, with an optional leading sign applied.</li>
164+
* </ul>
165+
* </p>
166+
*
167+
* <p>
168+
* Example generator strings:
169+
* <ul>
170+
* <li>"a b ab" – two main factors a, b, and one combination factor ab.</li>
171+
* <li>"a b -ab" – two main factors a, b, and one combination factor ab with a negative sign applied.</li>
172+
* </ul>
173+
* </p>
174+
*
175+
* <p>
176+
* Steps performed by this method:
177+
* <ol>
178+
* <li>Validate the generator string using {@link FactorialUtility#validateGeneretor(String)}.</li>
179+
* <li>Parse the generator into main factors and combination factors.</li>
180+
* <li>Generate a 2-level full factorial design for the main factors.</li>
181+
* <li>Populate the final design matrix with main factor values.</li>
182+
* <li>For each combination factor, compute the row-wise product of its associated main factor columns.</li>
183+
* <li>If a leading sign ('+' or '-') exists for a combination factor, apply it to the computed product.</li>
184+
* <li>Populate the final design matrix with the computed combination factor values.</li>
185+
* <li>Log the final matrix for inspection.</li>
186+
* </ol>
187+
* </p>
188+
*
189+
* <p>
190+
* Notes:
191+
* <ul>
192+
* <li>The number of rows in the final matrix is 2^k, where k is the number of main factors.</li>
193+
* <li>The number of columns equals the total number of factors in the generator string (main + combination).</li>
194+
* <li>Combination factors can involve multiple main factors.</li>
195+
* <li>Leading '+' signs are optional and do not modify the product; leading '-' signs negate the product.</li>
196+
* </ul>
197+
* </p>
198+
*
199+
* @param generetor
200+
* A generator string defining main factors and combination factors. Main factors are single letters,
201+
* combination factors are multiple letters possibly prefixed with '+' or '-' to indicate sign.
202+
*
203+
* @throws IllegalArgumentException
204+
* If the generator string is invalid according to {@link FactorialUtility#validateGeneretor(String)}.
205+
*
206+
* @see FactorialUtility#validateGeneretor(String)
207+
*/
208+
public static RealMatrix fractionalFactorial( String generetor ) {
150209
Array2DRowRealMatrix matrixFactory = new Array2DRowRealMatrix();
151210
// validation
152211
FactorialUtility.validateGeneretor( generetor );
@@ -166,56 +225,55 @@ public static void fractionalFactorial( String generetor ) {
166225
}
167226
}
168227
// main design factor 2 level full factorial matrix
169-
int[] fullFactorialParam = new int[ mainDesignFactorIndexList.size() ];
170-
List< RealMatrix > mainDesignFactor2LFFMatrixList = new ArrayList<>();
171-
for ( int i = 0; mainDesignFactorIndexList.size() > i; i++ ) {
172-
mainDesignFactor2LFFMatrixList.add( fullFactorial2Level( 1 ) );
173-
fullFactorialParam[ i ] = 2; // fixed level size
174-
}
228+
RealMatrix mainDesignFactors2LFFMatrix = fullFactorial2Level( mainDesignFactorIndexList.size() );
175229
// creating the final result matrix
176-
Integer rowNum = fullFactorial( fullFactorialParam ).getRowDimension();
230+
Integer rowNum = fullFactorial2Level( mainDesignFactorIndexList.size() ).getRowDimension();
177231
Integer colNum = factorList.size();
178232
RealMatrix finalDesignMatrix = matrixFactory.createMatrix( rowNum, colNum );
179233

180234
// computing and populating matrix for main design factor factorial first
181-
for ( Integer mainDesignFactorIndexValue :mainDesignFactorIndexList) {
182-
for ( int i = 0; mainDesignFactor2LFFMatrixList.size() > i; i++ ) {
183-
RealMatrix currentMainDesignFactorMatrix = mainDesignFactor2LFFMatrixList.get( i );
184-
for ( int j = 0; currentMainDesignFactorMatrix.getRowDimension() >= j; j++ ) {
185-
double currentMainDesignFactorMatrixValue = currentMainDesignFactorMatrix.getRow( j )[ 0 ];
186-
finalDesignMatrix.setEntry( j, mainDesignFactorIndexValue, currentMainDesignFactorMatrixValue );
187-
}
235+
for ( Integer mainDesignFactorIndexValue : mainDesignFactorIndexList ) {
236+
for ( int j = 0; mainDesignFactors2LFFMatrix.getRowDimension() > j; j++ ) {
237+
double currentMainDesignFactorMatrixValue = mainDesignFactors2LFFMatrix.getRow( j )[ mainDesignFactorIndexValue ];
238+
finalDesignMatrix.setEntry( j, mainDesignFactorIndexValue, currentMainDesignFactorMatrixValue );
188239
}
189240
}
190241
// computing combination design factor and populate the final design matrix with it
191-
//? worry about the "-" and "+" cases in the genereter later first populate with product
192242
for ( Integer combinationDesignFactorIndexValue : combinationDesignFactorsIndexList ) {
193-
String[] factorCombinationSplit = factorList.get( combinationDesignFactorIndexValue ).split( "" );
194-
/////////////// matching mainDesingnFactor ///////////////////////////////
243+
String signOfCurrentCombinationDesignFactor = "";
244+
List< String > factorCombinationSplit = Arrays.asList( factorList.get( combinationDesignFactorIndexValue ).split( "" ) );
245+
if ( factorList.get( combinationDesignFactorIndexValue ).startsWith( "-" ) || factorList.get(
246+
combinationDesignFactorIndexValue ).startsWith( "+" ) ) {
247+
signOfCurrentCombinationDesignFactor = factorList.get( combinationDesignFactorIndexValue ).split( "" )[0];
248+
}
195249
List< Integer > matchingMainFactorFinalMatrixIndexList = new ArrayList<>();
196-
for ( int c = 0; factorCombinationSplit.length > c; c++ ) {
250+
for ( int c = 0; factorCombinationSplit.size() > c; c++ ) {
197251
for ( int m = 0; mainDesignFactorIndexList.size() > m; m++ ) {
198252
String currDesignFactorName = factorList.get( m );
199-
if ( factorCombinationSplit[ c ].equalsIgnoreCase( currDesignFactorName ) ) {
253+
if ( factorCombinationSplit.get( c ).equalsIgnoreCase( currDesignFactorName ) ) {
200254
matchingMainFactorFinalMatrixIndexList.add( m );
201255
}
202256
}
203257
}
204-
//////////////////////////////////////////////////////////////
205-
double mainFactorsProductValue = 1.0;
206-
for ( int c = 0; matchingMainFactorFinalMatrixIndexList.size() > c; c++ ) {
207-
for ( int r = 0; finalDesignMatrix.getRowDimension() > r; r++ ) {
258+
for ( int r = 0; finalDesignMatrix.getRowDimension() > r; r++ ) {
259+
double mainFactorsProductValue = 1.0;
260+
for ( int c = 0; matchingMainFactorFinalMatrixIndexList.size() > c; c++ ) {
208261
double mainFactorValue = finalDesignMatrix.getEntry( r, c );
209262
mainFactorsProductValue *= mainFactorValue;
210263
}
211-
for ( int r = 0; finalDesignMatrix.getRowDimension() > r; r++ ) {
212-
// setting the combination factor value in the final matrix
213-
finalDesignMatrix.setEntry( r, combinationDesignFactorIndexValue, mainFactorsProductValue );
264+
if ( !signOfCurrentCombinationDesignFactor.isBlank() ) { // condition to handle signs in combination design factors
265+
if ( signOfCurrentCombinationDesignFactor.equalsIgnoreCase( "-" ) ) {
266+
mainFactorsProductValue = -mainFactorsProductValue;
267+
}
214268
}
269+
// setting the combination factor value in the final matrix
270+
finalDesignMatrix.setEntry( r, combinationDesignFactorIndexValue, mainFactorsProductValue );
215271
}
216272
}
217273

218-
log.info( finalDesignMatrix );
274+
log.info("Fractional Factorial Result Matrix: " + finalDesignMatrix );
275+
276+
return finalDesignMatrix;
219277
}
220278

221279
}

0 commit comments

Comments
 (0)