Hide keyboard shortcuts

Hot-keys on this page

r m x p   toggle line displays

j k   next/prev highlighted chunk

0   (zero) top of page

1   (one) first highlighted chunk

1""" 

2box_wilson: Box-Wilson experiment designs, sometimes referred to as Central-Composite Designs 

3(CCDs), are useful for measuring quadratic effects. 

4 

5Linear effects are typically measured using 2 level factorial or 2 level Plackett-Burman 

6experiments. However, if the relationship between treatments and response are quadratic, more than 

72 levels may be required to accurately represent the response surface of the experiment. 

8 

9CCDs allow experimenters to model quadratic response surfaces without implementing full 3 level 

10factorial experiments. CCD designs consist of three "runs": A) a factorial experiment (sometimes 

11fractional in design) B) a set of center points, experimental runs whose values of each factor are 

12the medians of the values used in the factorial portion C) a set of axial points, experimental runs 

13identical to the centre points except for one factor, which will take on values both below and 

14above the median of the two factorial levels. 

15 

16| A) corner points (defined by the factorial design or matrix_f) 

17| B) center points (defined by the matrix_c) 

18| C) axial points (defined by the matrix_e) 

19 

20Axial points are sometimes referred to as star points. 

21 

22If the distance from the center of the design space to a factorial point is 1 unit for each 

23factor, the distance from the center of the design space to a star point is |alpha| > 1. The 

24precise value of alpha depends on the variables center, alpha_design, and face_design. 

25 

26In rare cases (i.e. k=2) a design can be orthogonal and rotatable. However, this is only 

27true in a vary limited number of cases. See the example below: 

28>>> design_box_wilson(k=2, alpha_design="orthogonal", center=(1,1), face_design="CCC") 

29>>> design_box_wilson(k=2, alpha_design="rotatable", center=(1,1), face_design="CCC") 

30 

31""" 

32 

33import logging 

34from typing import Optional, Tuple 

35 

36from numpy import zeros, ndarray, r_ 

37from pandas import DataFrame 

38 

39from lind.design.factorial import design_full_factorial 

40from lind._utilities import _check_int_input, _check_str_input 

41 

42# set logging 

43logging.basicConfig(level=logging.INFO) 

44logger = logging.getLogger(__name__) 

45 

46# define public functions (ignored by jupyter notebooks) 

47__all__ = ["design_box_wilson"] 

48 

49 

50#################################################################################################### 

51 

52 

53def _get_alpha(num_factors: int, alpha_design: Optional[str] = None, 

54 center: Tuple[int, int] = (1, 1)) -> [ndarray, float]: 

55 """ 

56 Find the distance measure `alpha` 

57 

58 Notes 

59 ----- 

60 * number of factorial points = 2.0**num_factors 

61 * number of axial points = 2*num_factors 

62 * factorial center position = center[0] 

63 * axial center position = center[1] 

64 * alpha is always 1 for CCF face_design (hence default behavior for alpha_design=None) 

65 * CCDs always contain twice as many star points (axial points) as factors. The star points 

66 represent new extreme values (low and high) for each factor. 

67 """ 

68 if alpha_design is None: 

69 return 1.0 

70 if alpha_design == 'orthogonal': 

71 # see Response Surface Methodology by Raymond Myers (1971) 

72 return ( 

73 num_factors * 

74 (1.0 + center[1] / (2.0*num_factors)) / 

75 (1.0 + center[0] / (2.0**num_factors)) 

76 )**0.5 

77 if alpha_design == 'rotatable': 

78 # see Section 5.3.3.6.1 of the Engineering Statistics Handbook for formula 

79 return (2.0**num_factors)**0.25 

80 raise ValueError("Invalid value for alpha_design: {}".format(alpha_design)) 

81 

82 

83def _get_matrix_f(num_factors): 

84 """2 level full factorial experiment design defines the matrix_f""" 

85 return design_full_factorial([[-1, 1] for _ in range(num_factors)]).values 

86 

87 

88def _get_matrix_c(num_factors): 

89 """Generate the center point matrix""" 

90 matrix_c = zeros((2*num_factors, num_factors)) 

91 for i in range(num_factors): 

92 matrix_c[2*i:2*i+2, i] = [-1, 1] 

93 return matrix_c 

94 

95 

96#################################################################################################### 

97 

98 

99def design_box_wilson(k: int, alpha_design: Optional[str] = "rotatable", 

100 center: Optional[Tuple[int, int]] = (1, 1), 

101 face_design: Optional[str] = "CCC") -> DataFrame: 

102 """ 

103 boc_wilson: Central Composite Design (CCD) 

104 

105 A CCD design contains an embedded factorial design with center points 

106 that are augmented with a group of 'star points' that allow estimation of curvature useful for 

107 estimating quadratic relationships. 

108 

109 CCD designs can use facing options: CCC (Circumscribed), CCI (Inscribed), and 

110 CCF (Face Centered). 

111 

112 CCC designs are the original form of the central composite design. The star points are at some 

113 distance alpha from the center based on the properties desired for the design and the number of 

114 factors in the design. The star points establish new extremes for the low and high settings for 

115 all factors. These designs have circular, spherical, or hyperspherical symmetry and require 5 

116 levels for each factor. Augmenting an existing factorial or resolution V fractional factorial 

117 design with star points can produce this design. 

118 

119 CCI is useful in situations where the limits specified for factor settings are truly limits, the 

120 CCI design uses the factor settings as the star points and creates a factorial design within 

121 those limits (in other words, a CCI design is a scaled down CCC design with each factor level of 

122 the CCC design divided by alpha to generate the CCI design). This design also requires 5 levels 

123 of each factor. CCI designs can use partial factorial designs for matrix_f. This is not 

124 supported here. 

125 

126 CCF design star points are at the center of each face of the factorial space, so alpha=1. This 

127 requires 3 levels of each factor. Augmenting an existing factorial or resolution V design with 

128 appropriate star points can also produce this design. 

129 

130 Parameters 

131 ---------- 

132 k: int 

133 the total number of factors considered in the design 

134 alpha_design: str, optional 

135 The method of calculating the distance alpha. Available options: `orthogonal`, `rotatable`; 

136 Just like MATLAB ccdesign, `rotatable` is the default 

137 center: Tuple[int, int], optional 

138 the first value of the tuple is the factorial center point, the second value of the tuple 

139 is the axial center point; default value is (1, 1) 

140 face_design: str, optional 

141 this input determines the symmetry / geometric of the design; valid options are: `CCC`, 

142 `CCF`, and `CCI` 

143 

144 Returns 

145 ------- 

146 pd.DataFrame 

147 the box-wilson experimental design 

148 

149 Examples 

150 -------- 

151 >>> design = design_box_wilson(k=2, alpha_design="rotatable", center=(1,1), face_design="CCC") 

152 

153 References 

154 ---------- 

155 NIST 

156 * Section 5.3.3.6.1 of the Engineering Statistics Handbook 

157 Myers 

158 * Response Surface Methodology (1971) 

159 Box and Wilson 

160 * On the Experimental Attainment of Optimum Conditions (1951) 

161 

162 Notes 

163 ----- 

164 * When face_design=`CCF` the alpha_design argument is ignored and alpha is set to 1. 

165 * Popular CCD designs are orthogonal (OCCD), rotatable (RCCD), face (FCC), spherical (SCCD), 

166 and Slope Rotatable (Slope-R); of these only the first three are supported 

167 

168 """ 

169 

170 k = _check_int_input(k, "k") 

171 alpha_design = _check_str_input(alpha_design, "alpha_design", ["orthogonal", "rotatable"]) 

172 face_design = _check_str_input(face_design, "face_design", ["CCC", "CCF", "CCI"]) 

173 

174 if k < 2: 

175 raise ValueError("Input k must be >= 2 to produce a valid design.") 

176 

177 center = center if alpha_design == "orthogonal" else (1, 1) 

178 alpha = _get_alpha(k, alpha_design=alpha_design, center=center) if \ 

179 face_design != "ccf" else 1.0 

180 

181 matrix_f = _get_matrix_f(k) 

182 matrix_c = _get_matrix_c(k) 

183 

184 # Circumscribed Face (CCC) 

185 if face_design == "ccc": 

186 matrix_c = matrix_c * alpha 

187 

188 # Inscribed Face (CCI) 

189 elif face_design == "cci": 

190 # normalize matrix_f by distance alpha 

191 matrix_f = matrix_f / alpha 

192 

193 # Faced Centered Face (CCF): alpha is always 1 

194 

195 center_1 = zeros((center[0], k)) 

196 center_2 = zeros((center[1], k)) 

197 

198 return DataFrame(data=r_[ 

199 r_[matrix_f, center_1], 

200 r_[matrix_c, center_2] 

201 ], columns=["x{}".format(i) for i in range(k)])