Skip to content

Commit 12ef63c

Browse files
composite doe implementation
1 parent fc0072a commit 12ef63c

13 files changed

Lines changed: 577 additions & 43 deletions

File tree

dependency-reduced-pom.xml

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
3+
<modelVersion>4.0.0</modelVersion>
4+
<groupId>com.jdoe</groupId>
5+
<artifactId>doe-genereter</artifactId>
6+
<name>JDOE</name>
7+
<version>1.0-SNAPSHOT</version>
8+
<url>http://maven.apache.org</url>
9+
<build>
10+
<plugins>
11+
<plugin>
12+
<artifactId>maven-jar-plugin</artifactId>
13+
<version>3.4.1</version>
14+
<configuration>
15+
<archive>
16+
<manifest>
17+
<mainClass>com.jdoe.Testing</mainClass>
18+
</manifest>
19+
</archive>
20+
</configuration>
21+
</plugin>
22+
<plugin>
23+
<artifactId>maven-shade-plugin</artifactId>
24+
<version>3.6.1</version>
25+
<executions>
26+
<execution>
27+
<phase>package</phase>
28+
<goals>
29+
<goal>shade</goal>
30+
</goals>
31+
<configuration>
32+
<transformers>
33+
<transformer />
34+
</transformers>
35+
</configuration>
36+
</execution>
37+
</executions>
38+
</plugin>
39+
</plugins>
40+
</build>
41+
<dependencies>
42+
<dependency>
43+
<groupId>junit</groupId>
44+
<artifactId>junit</artifactId>
45+
<version>4.13.2</version>
46+
<scope>test</scope>
47+
<exclusions>
48+
<exclusion>
49+
<artifactId>hamcrest-core</artifactId>
50+
<groupId>org.hamcrest</groupId>
51+
</exclusion>
52+
</exclusions>
53+
</dependency>
54+
<dependency>
55+
<groupId>org.mockito</groupId>
56+
<artifactId>mockito-core</artifactId>
57+
<version>5.20.0</version>
58+
<scope>test</scope>
59+
<exclusions>
60+
<exclusion>
61+
<artifactId>byte-buddy</artifactId>
62+
<groupId>net.bytebuddy</groupId>
63+
</exclusion>
64+
<exclusion>
65+
<artifactId>byte-buddy-agent</artifactId>
66+
<groupId>net.bytebuddy</groupId>
67+
</exclusion>
68+
<exclusion>
69+
<artifactId>objenesis</artifactId>
70+
<groupId>org.objenesis</groupId>
71+
</exclusion>
72+
</exclusions>
73+
</dependency>
74+
<dependency>
75+
<groupId>org.mockito</groupId>
76+
<artifactId>mockito-inline</artifactId>
77+
<version>5.2.0</version>
78+
<scope>test</scope>
79+
</dependency>
80+
</dependencies>
81+
<properties>
82+
<maven.compiler.target>17</maven.compiler.target>
83+
<maven.compiler.source>17</maven.compiler.source>
84+
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
85+
</properties>
86+
</project>

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

Lines changed: 74 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -9,103 +9,134 @@
99

1010
public class CompositeDOE {
1111

12-
private static final String[] alphaParamLegalExpressions = { "orthogonal", "o", "rotatable", "r" };
12+
private static final String[] alphaParamLegalExpressions = {"orthogonal", "o", "rotatable", "r"};
1313

14-
private static final String[] faceParamLegalExpressions = { "circumscribed", "ccc", "inscribed", "cci", "faced", "ccf" };
14+
private static final String[] faceParamLegalExpressions = {"circumscribed", "ccc", "inscribed", "cci", "faced", "ccf"};
1515

16-
public static void centralCompositeDesign( @NotNull int numberOfFactors, @NotNull int[] centerPoints, @NotNull String alpha,
17-
@NotNull String face ) {
16+
public static RealMatrix centralCompositeDesign(@NotNull int numberOfFactors, @NotNull int[] centerPoints, @NotNull String alpha, @NotNull String face) {
17+
validateCompositeDegisnParameters(numberOfFactors, centerPoints, alpha, face);
1818

19-
validateCompositeDegisnParameters( numberOfFactors, centerPoints, alpha, face );
19+
RealMatrix factorialDesignMatrix;
20+
RealMatrix starDesignMatrix;
21+
double alphaValue;
2022

21-
RealMatrix fullFactorial2LevelMatrix = FactorialDOE.fullFactorial2Level( numberOfFactors );
23+
// Orthogonal Design
24+
if (alpha.toLowerCase().equals("orthogonal") || alpha.toLowerCase().equals("o")) {
25+
Object[] starResult = StarDOE.star(numberOfFactors, "orthogonal", centerPoints);
26+
starDesignMatrix = new Array2DRowRealMatrix((double[][]) starResult[0]); // Convert array to RealMatrix
27+
alphaValue = (double) starResult[1];
28+
}
29+
// Rotatable Design
30+
else if (alpha.toLowerCase().equals("rotatable") || alpha.toLowerCase().equals("r")) {
31+
Object[] starResult = StarDOE.star(numberOfFactors, "rotatable", new int[]{0, 0});
32+
starDesignMatrix = new Array2DRowRealMatrix((double[][]) starResult[0]); // Convert array to RealMatrix
33+
alphaValue = (double) starResult[1];
34+
} else {
35+
throw new IllegalArgumentException("Invalid alpha parameter: " + alpha);
36+
}
37+
38+
// Inscribed CCD
39+
if (face.toLowerCase().equals("inscribed") || face.toLowerCase().equals("cci")) {
40+
factorialDesignMatrix = FactorialDOE.fullFactorial2Level(numberOfFactors);
41+
factorialDesignMatrix = factorialDesignMatrix.scalarMultiply(1.0 / alphaValue); // Scale down the factorial points
42+
Object[] starResult = StarDOE.star(numberOfFactors, alpha, centerPoints);
43+
starDesignMatrix = new Array2DRowRealMatrix((double[][]) starResult[0]); // Convert array to RealMatrix
44+
alphaValue = (double) starResult[1];
45+
}
46+
// Faced CCD
47+
else if (face.toLowerCase().equals("faced") || face.toLowerCase().equals("ccf")) {
48+
Object[] starResult = StarDOE.star(numberOfFactors, alpha, centerPoints);
49+
starDesignMatrix = new Array2DRowRealMatrix((double[][]) starResult[0]); // Convert array to RealMatrix
50+
alphaValue = 1.0;
51+
// Value of alpha is always 1 in Faced CCD
52+
factorialDesignMatrix = FactorialDOE.fullFactorial2Level(numberOfFactors);
53+
}
54+
// Circumscribed CCD
55+
else if (face.toLowerCase().equals("circumscribed") || face.toLowerCase().equals("ccc")) {
56+
factorialDesignMatrix = FactorialDOE.fullFactorial2Level(numberOfFactors);
57+
} else {
58+
throw new IllegalArgumentException("Invalid face parameter: " + face);
59+
}
2260

61+
RealMatrix centerPointsMatrix1 = RepeatCenterDOE.repeatCenter(numberOfFactors, centerPoints[0]);
62+
RealMatrix centerPointsMatrix2 = RepeatCenterDOE.repeatCenter(numberOfFactors, centerPoints[1]);
63+
64+
factorialDesignMatrix = UnionDOE.matrixUnion(factorialDesignMatrix, centerPointsMatrix1);
65+
starDesignMatrix = UnionDOE.matrixUnion(starDesignMatrix, centerPointsMatrix2);
66+
RealMatrix finalDesignMatrix = UnionDOE.matrixUnion(factorialDesignMatrix, starDesignMatrix);
67+
68+
return finalDesignMatrix;
2369
}
2470

2571
//<-----------------------------Utility Methods---------------------------------->
2672

27-
public static void validateCompositeDegisnParameters( int numberOfFactors, int[] centerPoints, String alpha, String face ) {
28-
if ( numberOfFactors < 1 ) {
29-
throw new IllegalArgumentException( "number of factors must be greater then 1" );
73+
public static void validateCompositeDegisnParameters(int numberOfFactors, int[] centerPoints, String alpha, String face) {
74+
if (numberOfFactors < 1) {
75+
throw new IllegalArgumentException("number of factors must be greater than 1");
3076
}
31-
if ( centerPoints.length == 2 ) {
32-
throw new IllegalArgumentException(
33-
String.format( "Invalid number of values for \"center\" (expected 2, but got %d )", centerPoints.length ) );
77+
if (centerPoints.length != 2) { // Fixed: was == now !=
78+
throw new IllegalArgumentException(String.format("Invalid number of values for \"center\" (expected 2, but got %d)", centerPoints.length));
3479
}
35-
if ( validateExpression( alpha, alphaParamLegalExpressions ) == Boolean.FALSE ) {
36-
throw new IllegalArgumentException(
37-
String.format( "Invalid value for \"alpha\" (expected format %d )", alphaParamLegalExpressions.toString() ) );
80+
if (validateExpression(alpha, alphaParamLegalExpressions) == Boolean.FALSE) {
81+
throw new IllegalArgumentException(String.format("Invalid value for \"alpha\" (expected one of %s)", java.util.Arrays.toString(alphaParamLegalExpressions)));
3882
}
39-
if ( validateExpression( alpha, faceParamLegalExpressions ) == Boolean.FALSE ) {
40-
throw new IllegalArgumentException(
41-
String.format( "Invalid value for \"face\" (expected format %d )", faceParamLegalExpressions.toString() ) );
83+
if (validateExpression(face, faceParamLegalExpressions) == Boolean.FALSE) {
84+
throw new IllegalArgumentException(String.format("Invalid value for \"face\" (expected one of %s)", java.util.Arrays.toString(faceParamLegalExpressions)));
4285
}
4386
}
4487

45-
public static Boolean validateExpression( String expression, String[] legalExpressions ) {
88+
public static Boolean validateExpression(String expression, String[] legalExpressions) {
4689
Boolean validInput = Boolean.FALSE;
47-
for ( String legalExpression : legalExpressions ) {
48-
if ( legalExpression.equals( expression ) ) {
90+
for (String legalExpression : legalExpressions) {
91+
if (legalExpression.equals(expression)) {
4992
validInput = Boolean.TRUE;
5093
break;
5194
}
5295
}
5396
return validInput;
5497
}
5598

56-
public static Boolean matrixUnion( RealMatrix firstMatrix, RealMatrix secondMatrix ) {
57-
double[][] finalMatrixRowModel = new double[ firstMatrix.getRowDimension() + secondMatrix.getRowDimension() ][];
58-
for ( int i = 0; i < firstMatrix.getRowDimension(); i++ ) {
59-
finalMatrixRowModel[ i ] = firstMatrix.getRow( i );
60-
}
61-
for ( int i = 0; i < secondMatrix.getRowDimension(); i++ ) {
62-
finalMatrixRowModel[ i ] = secondMatrix.getRow( i );
63-
}
64-
RealMatrix finalMatrix = new Array2DRowRealMatrix(finalMatrixRowModel);
65-
GenericDOEUtil.matrixLogger( finalMatrix, "matrixUnion" );
66-
}
67-
6899
}
69100

70101
//<-----------------------------STEPS---------------------------------->
71102

72103
/**
73104
* Detailed Steps to Port Central Composite Design Script to Java
74-
*
105+
* <p>
75106
* $ 1. Create CompositeDOE Class Structure Create CompositeDOE.java in com.jdoe.algorithms package Add imports:
76107
* org.apache.commons.math3.linear.* for matrix operations Define method signature: public static RealMatrix centralCompositeDesign(int n,
77108
* int[] center, String alpha, String face) Set default parameters handling for center, alpha, and face
78-
*
109+
* <p>
79110
* $ 2. Implement Input Validation Logic Add assertion: assert n > 1 : "\"n\" must be an integer greater than 1" Validate alpha parameter
80111
* with: alpha.toLowerCase() and check against allowed values Validate face parameter with: face.toLowerCase() and check against allowed
81112
* values Validate center array length: if (center.length != 2) throw IllegalArgumentException Format error messages to match Python
82113
* implementation
83-
*
114+
* <p>
84115
* $ 3. Implement Star Point Generation Create StarDOE.java class with star method Calculate alpha based on alpha type: For orthogonal:
85116
* alpha = Math.pow(2 * factorial(n), 0.25) where factorial(n) = n! For rotatable: alpha = Math.pow(2, 0.5) for 2D, Math.pow(3, 0.5) for 3D,
86117
* etc. Generate 2n star points with values [±alpha, 0, ..., 0], [0, ±alpha, ..., 0], etc. Return both star matrix and alpha value as an
87118
* Object array
88-
*
119+
* <p>
89120
* 4. Enhance FactorialDOE Class Add ff2n method that generates 2-level factorial design Create 2^n × n matrix with values -1 and +1 Use bit
90121
* manipulation: for each row i and column j, set value to ((i >> j) & 1) == 0 ? -1 : 1 Return RealMatrix object
91-
*
122+
* <p>
92123
* 5. Create UnionDOE Class Implement union method that combines two matrices vertically Use Array2DRowRealMatrix constructor to create new
93124
* matrix with combined rows Copy data from both input matrices to the result matrix Return the concatenated matrix
94-
*
125+
* <p>
95126
* 6. Create RepeatCenterDOE Class Implement repeatCenter method that generates center points Create repeats × n matrix filled with zeros
96127
* Use new Array2DRowRealMatrix(repeats, n) to initialize matrix Return the center point matrix
97-
*
128+
* <p>
98129
* 7. Implement Core Algorithm Logic Initialize H1 andH2 matrices based on face type For inscribed (cci): scale factorial points H1 =
99130
* H1.scalarMultiply(1.0/a) For faced (ccf): set alpha to 1.0 For circumscribed (ccc): keep original factorial points Generate center points
100131
* C1 and C2 using repeatCenter Combine matrices: H1 = union(H1, C1), H2 = union(H2, C2), H = union(H1, H2)
101-
*
132+
* <p>
102133
* 8. Handle Matrix Operations Implement matrix scaling using scalarMultiply() method from Commons Math Ensure all matrix dimensions are
103134
* compatible for union operations Use getSubMatrix() and setSubMatrix() for matrix manipulations Return final RealMatrix object
104-
*
135+
* <p>
105136
* 9. Create Unit Tests Create CompositeDOETest.java with comprehensive test cases Test all three face types: ccc, cci, ccf Test both alpha
106137
* types: orthogonal, rotatable Validate matrix dimensions: (2^n + 2n + sum(center)) × n Verify center point counts and star point
107138
* distances
108-
*
139+
* <p>
109140
* 10. Add Documentation and Error Handling Add JavaDoc explaining parameters, return value, and exceptions Implement proper exception
110141
* handling for invalid inputs Include example usage in documentation Follow the same error message format as Python implementation
111142
*/
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
package com.jdoe.algorithms;
2+
3+
import org.apache.commons.math3.linear.Array2DRowRealMatrix;
4+
import org.apache.commons.math3.linear.RealMatrix;
5+
6+
public class RepeatCenterDOE {
7+
8+
public static RealMatrix repeatCenter(int numberOfFactors, int repeats) {
9+
return new Array2DRowRealMatrix(repeats, numberOfFactors);
10+
}
11+
12+
}
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
package com.jdoe.algorithms;
2+
3+
import com.jdoe.util.GenericDOEUtil;
4+
5+
public class StarDOE {
6+
/**
7+
* Create the star points of various design matrices
8+
*
9+
* @param n The number of variables in the design
10+
* @param alpha Available values are 'faced' (default), 'orthogonal', or 'rotatable'
11+
* @param center A 1-by-2 array of integers indicating the number of center points
12+
* assigned in each block of the response surface design. Default is (1, 1).
13+
* @return A two-element array containing the star-point portion of the design matrix
14+
* and the alpha value to scale the star points with.
15+
*/
16+
public static Object[] star(int n, String alpha, int[] center) {
17+
double a;
18+
// Star points at the center of each face of the factorial
19+
if ("faced".equals(alpha)) {
20+
a = 1.0;
21+
} else if ("orthogonal".equals(alpha)) {
22+
int nc = (int) Math.pow(2, n); // factorial points
23+
int nco = center[0]; // center points to factorial
24+
int na = 2 * n; // axial points
25+
int nao = center[1]; // center points to axial design
26+
// value of alpha in orthogonal design
27+
a = Math.sqrt(n * (1 + (double) nao / na) / (1 + (double) nco / nc));
28+
} else if ("rotatable".equals(alpha)) {
29+
int nc = (int) Math.pow(2, n); // number of factorial points
30+
a = Math.pow(nc, 0.25); // value of alpha in rotatable design
31+
} else {
32+
throw new IllegalArgumentException("Invalid value for \"alpha\": " + alpha);
33+
}
34+
// Create the actual matrix now.
35+
double[][] H = new double[2 * n][n];
36+
for (int i = 0; i < n; i++) {
37+
H[2 * i][i] = -1.0;
38+
H[2 * i + 1][i] = 1.0;
39+
}
40+
// Multiply matrix by alpha
41+
for (int i = 0; i < H.length; i++) {
42+
for (int j = 0; j < H[i].length; j++) {
43+
H[i][j] *= a;
44+
}
45+
}
46+
return new Object[]{H, a};
47+
}
48+
49+
/**
50+
* Overloaded method with default center value (1, 1)
51+
*/
52+
public static Object[] star(int n, String alpha) {
53+
return star(n, alpha, new int[]{1, 1});
54+
}
55+
56+
/**
57+
* Overloaded method with default alpha value "faced" and default center value (1, 1)
58+
*/
59+
public static Object[] star(int n) {
60+
return star(n, "faced", new int[]{1, 1});
61+
}
62+
63+
}
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
package com.jdoe.algorithms;
2+
3+
import com.jdoe.util.GenericDOEUtil;
4+
import org.apache.commons.math3.linear.Array2DRowRealMatrix;
5+
import org.apache.commons.math3.linear.RealMatrix;
6+
7+
public class UnionDOE {
8+
public static RealMatrix matrixUnion(RealMatrix firstMatrix, RealMatrix secondMatrix) {
9+
int totalRows = firstMatrix.getRowDimension() + secondMatrix.getRowDimension();
10+
int cols = firstMatrix.getColumnDimension();
11+
12+
// Verify both matrices have the same number of columns
13+
if (cols != secondMatrix.getColumnDimension()) {
14+
throw new IllegalArgumentException("Both matrices must have the same number of columns");
15+
}
16+
17+
double[][] finalMatrixRowModel = new double[totalRows][cols];
18+
19+
// Copy rows from the first matrix
20+
for (int i = 0; i < firstMatrix.getRowDimension(); i++) {
21+
finalMatrixRowModel[i] = firstMatrix.getRow(i);
22+
}
23+
24+
// Copy rows from the second matrix starting after the first matrix's rows
25+
for (int i = 0; i < secondMatrix.getRowDimension(); i++) {
26+
finalMatrixRowModel[firstMatrix.getRowDimension() + i] = secondMatrix.getRow(i);
27+
}
28+
29+
RealMatrix finalMatrix = new Array2DRowRealMatrix(finalMatrixRowModel);
30+
GenericDOEUtil.matrixLogger(finalMatrix, "matrixUnion");
31+
return finalMatrix;
32+
}
33+
}

0 commit comments

Comments
 (0)