Fractional Factorial Designs¶
Fractional factorial designs run only a carefully selected subset of the full factorial design, reducing experimental cost while still providing valuable information about main effects and important interactions.
When to Use Fractional Factorial Designs¶
- Many factors to screen: 5 or more factors where full factorial is too expensive
- Limited resources: When experimental runs are costly or time-consuming
- Screening studies: To identify the most important factors before detailed study
- Sequential experimentation: As a first step before running a full factorial on important factors
Key Concepts¶
Aliasing (Confounding)¶
In fractional factorial designs, some effects are aliased (confounded) with others. This means you cannot distinguish between aliased effects from the experimental data alone.
Resolution¶
Resolution describes the quality of a fractional factorial design:
- Resolution III: Main effects are not aliased with each other (but may be aliased with 2-factor interactions)
- Resolution IV: Main effects are not aliased with each other or 2-factor interactions
- Resolution V: Main effects and 2-factor interactions are not aliased with each other
Generators¶
Generators define how the fractional design is constructed. For example, in a 2^(4-1) design with generator D=ABC, factor D is set equal to the product of factors A, B, and C.
Basic Usage¶
Simple Fractional Factorial¶
import daspi as dsp
# 2^(3-1) design: 4 runs instead of 8
A = dsp.Factor('A', (-1, 1))
B = dsp.Factor('B', (-1, 1))
C = dsp.Factor('C', (-1, 1))
builder = dsp.FractionalFactorialDesignBuilder(
A, B, C,
generators=['C=AB'] # C is determined by A×B
)
design = builder.build_design(corrected=False)
print(design)
Using Default Generators¶
For common designs, you can use standard generators:
# Get standard generators for 2^(5-2) design
generators = dsp.get_default_generators(k=5, p=2)
print(generators) # ['D=AB', 'E=AC']
# Create the design
A = dsp.Factor('A', (-1, 1))
B = dsp.Factor('B', (-1, 1))
C = dsp.Factor('C', (-1, 1))
D = dsp.Factor('D', (-1, 1))
E = dsp.Factor('E', (-1, 1))
builder = dsp.FractionalFactorialDesignBuilder(
A, B, C, D, E,
generators=generators
)
design = builder.build_design(corrected=False)
Foldover Designs¶
Foldover adds a second fraction where the signs of one or more factors are reversed, helping to resolve aliasing between main effects and 2-factor interactions.
Complete Foldover¶
# Foldover all factors
builder = dsp.FractionalFactorialDesignBuilder(
A, B, C,
generators=['C=AB'],
fold=True # Reverses all factors
)
design = builder.build_design(corrected=False)
# This creates 8 runs total (4 original + 4 foldover)
Partial Foldover¶
# Foldover only factor A
builder = dsp.FractionalFactorialDesignBuilder(
A, B, C,
generators=['C=AB'],
fold='A' # Reverses only factor A
)
design = builder.build_design(corrected=False)
Common Fractional Factorial Designs¶
| Design | Basic Factors | Generated Factors | Generators | Resolution |
|---|---|---|---|---|
| 2^(3-1) | A, B | C | C=AB | III |
| 2^(4-1) | A, B, C | D | D=ABC | IV |
| 2^(5-2) | A, B, C | D, E | D=AB, E=AC | III |
| 2^(6-3) | A, B, C | D, E, F | D=AB, E=AC, F=BC | III |
| 2^(7-3) | A, B, C, D | E, F, G | E=ABC, F=ABD, G=BCD | IV |
Design Strategy¶
- Start small: Use a fractional factorial to screen many factors
- Analyze results: Identify the most important factors
- Follow up: Run a full factorial or higher-resolution fractional factorial on important factors
- Use foldover: If main effects are confounded with 2-factor interactions
Advanced Features¶
With Blocking and Replication¶
builder = dsp.FractionalFactorialDesignBuilder(
A, B, C, D, E,
generators=['D=AB', 'E=AC'],
replicates=2,
central_points=3,
blocks=2, # Split into 2 blocks
fold=True,
shuffle=True
)
design = builder.build_design(corrected=False)
API Reference¶
daspi.doe.FractionalFactorialDesignBuilder(*factors, generators, fold=False, replicates=1, central_points=0, blocks=1, shuffle=True)
¶
Bases: BaseDesignBuilder
Builder for 2-level fractional factorial designs with optional foldover.
This class supports the construction of regular 2-level fractional factorial designs using generator strings (e.g., 'C=AB'), and can optionally add a foldover to the design.
Default generators for common designs (see also get_default_generators):
| Design | Basic Factors | Generators | Example Generator Strings |
|---|---|---|---|
| 2^(3-1) | A, B | C = AB | ['C=AB'] |
| 2^(4-1) | A, B, C | D = ABC | ['D=ABC'] |
| 2^(5-2) | A, B, C | D = AB, E = AC | ['D=AB', 'E=AC'] |
| 2^(6-3) | A, B, C | D = AB, E = AC, F = BC | ['D=AB', 'E=AC', 'F=BC'] |
| 2^(7-3) | A, B, C, D | E = ABC, F = ABD, G = BCD | ['E=ABC', 'F=ABD', 'G=BCD'] |
| PARAMETER | DESCRIPTION |
|---|---|
factors
|
Factors defining the design space. All factors must have exactly 2 levels.
TYPE:
|
generators
|
List of generator strings that define how dependent factors are constructed from basic factors. For example, if you have 4 factors A, B, C, and D, you can set generators to ['C=AB', 'D=BC']. This means that factor C is defined as the product of factors A and B (C = A * B), and factor D as the product of B and C (D = B * C). The order of the generator strings should match the order of the dependent factors in the factors list. For common designs, see the table above or use get_default_generators(k, p).
TYPE:
|
fold
|
Whether to add a foldover. If True, a foldover will be added for all factors. If a string is provided, it should be the name of the factor to fold over. Default is False (no foldover).
TYPE:
|
replicates
|
Number of replicates. Must be positive, by default 1.
TYPE:
|
central_points
|
Number of central points to be added to each block. These are used to test linear effects. Must be non-negative. If set to 0, no central points are added. by default 0.
TYPE:
|
blocks
|
Number of blocks. Must be positive, by default 1.
TYPE:
|
shuffle
|
Whether to shuffle the design, by default True.
TYPE:
|
Examples:
Create a 2^(3-1) fractional factorial design (3 factors, 1 generator):
from daspi.doe.build import Factor, FractionalFactorialDesignBuilder
A = Factor('A', (-1, 1))
B = Factor('B', (-1, 1))
C = Factor('C', (-1, 1))
builder = FractionalFactorialDesignBuilder(A, B, C, generators=['C=AB'])
df = builder.build_design(corrected=False)
print(df)
std_order run_order central_point replica block A B C
0 0 0 1 1 1 -1 -1 1
1 1 1 1 1 1 -1 1 -1
2 2 2 1 1 1 1 -1 -1
3 3 3 1 1 1 1 1 1
Create the same design with foldover (doubles the number of runs, reverses A):
builder = FractionalFactorialDesignBuilder(
A, B, C, generators=['C=AB'], fold=True)
df = builder.build_design(corrected=False)
print(df)
std_order run_order central_point replica block A B C
0 0 0 1 1 1 -1 -1 1
1 1 1 1 1 1 -1 1 -1
2 2 2 1 1 1 1 -1 -1
3 3 3 1 1 1 1 1 1
4 4 4 1 1 1 1 -1 -1
5 5 5 1 1 1 1 1 1
6 6 6 1 1 1 -1 -1 1
7 7 7 1 1 1 -1 1 -1
| RAISES | DESCRIPTION |
|---|---|
AssertionError
|
If any of the parameters are invalid: - All factors must have exactly 2 levels. - Number of replicates must be positive. - Number of central points must be non-negative. - Number of blocks must be positive. - Generators must be provided as a list of strings. - Generators must match the number of dependent factors. - Each generator string must be in the format 'C=AB' where C is the dependent factor and AB are the independent factors. - Each dependent factor must be defined in the generators. - The first basic factor must be reversed in sign for foldover. |
Notes
In fractional factorial designs, only a subset of all possible factor combinations is run, which leads to confounding (aliasing) between main effects and interactions. Foldover is a technique to resolve some of these confoundings by running an additional set of experiments where the sign of one or more basic factors is reversed. This effectively doubles the number of runs and allows for the separation of certain effects that were aliased in the original fraction. Foldover is especially useful for identifying main effects that may be confounded with two-factor interactions in the initial design. Key points: - Foldover is meaningful only for regular 2-level fractional factorial designs, not for full factorials, non-regular designs, or designs with more than two levels per factor. - For full factorial designs, foldover is unnecessary because there is no aliasing to resolve. - For non-regular or mixed-level designs, the concept of foldover does not apply in the classical sense.
generators = generators
instance-attribute
¶
List of generator strings defining dependent factors.
by_resolution(*factors, resolution, fold=False, replicates=1, central_points=0, blocks=1, shuffle=True)
classmethod
¶
Create a FractionalFactorialDesignBuilder with generators chosen to achieve the specified resolution.
Resolution is a measure of design quality that indicates the degree of confounding between effects: - Resolution III: Main effects are not confounded with each other, but may be confounded with 2-factor interactions. - Resolution IV: Main effects are not confounded with 2-factor interactions, but 2-factor interactions may be confounded with each other. - Resolution V: Main effects and 2-factor interactions are not confounded with each other, but may be confounded with 3-factor interactions.
This method automatically selects standard generators that achieve the highest possible resolution for the given number of factors, or uses a fractional design if a full factorial would exceed the desired resolution constraints.
| PARAMETER | DESCRIPTION |
|---|---|
factors
|
Factors defining the design space. All factors must have exactly 2 levels.
TYPE:
|
resolution
|
Desired design resolution (III, IV, or V). Must be between 3 and 5.
TYPE:
|
fold
|
Whether to add a foldover. If True, a foldover will be added for all factors. If a string is provided, it should be the name of the factor to fold over. Default is False (no foldover).
TYPE:
|
replicates
|
Number of replicates. Must be positive, by default 1.
TYPE:
|
central_points
|
Number of central points to be added to each block. These are used to test linear effects. Must be non-negative. If set to 0, no central points are added. by default 0.
TYPE:
|
blocks
|
Number of blocks. Must be positive, by default 1.
TYPE:
|
shuffle
|
Whether to shuffle the design, by default True.
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
FractionalFactorialDesignBuilder
|
An instance configured with appropriate generators for the specified resolution. |
Examples:
Create a Resolution IV design with 5 factors:
import daspi as dsp
factors = [dsp.Factor(f'F{i}', (-1, 1)) for i in range(1, 6)]
builder = dsp.FractionalFactorialDesignBuilder.by_resolution(
*factors, resolution=4)
df = builder.build_design(corrected=True)
print(f"Design: 2^({len(factors)}-{len(builder.generators)})")
print(f"Runs: {len(df)}")
Create a Resolution V design with 7 factors:
import daspi as dsp
factors = [dsp.Factor(f'F{i}', (-1, 1)) for i in range(1, 8)]
builder = dsp.FractionalFactorialDesignBuilder.by_resolution(
*factors, resolution=5)
df = builder.build_design(corrected=True)
print(f"Design: 2^({len(factors)}-{len(builder.generators)})")
print(f"Runs: {len(df)}")
Raises ----__ AssertionError If any of the parameters are invalid: - All factors must have exactly 2 levels. - Resolution must be between 3 and 5. - Not enough factors for the specified resolution. ValueError If no standard generators are available for the required k and p combination.
Notes
This method uses standard generator sets optimized for the specified resolution. The generators are selected to achieve the highest resolution possible while minimizing the number of experimental runs.
Resolution selection guidelines: - Resolution III: Suitable for screening many factors when interactions are less important. - Resolution IV: Good balance between run count and ability to estimate main effects clearly. - Resolution V: Allows estimation of main effects and 2-factor interactions without confounding.
For the mathematical definition of resolution and aliasing patterns, see Montgomery (2017) "Design and Analysis of Experiments".
daspi.doe.get_default_generators(k, p)
¶
Return standard generators for regular 2-level fractional factorial designs.
| PARAMETER | DESCRIPTION |
|---|---|
k
|
Total number of factors.
TYPE:
|
p
|
Number of generators (fractionality, so design is 2^(k-p)).
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
List[str]
|
List of generator strings, e.g. ['C=AB', 'D=AC']. |
Notes
These are standard choices for high-resolution designs, suitable for most practical cases. For more, see Montgomery (2017), Box, Hunter & Hunter, or standard DOE tables.