Examine Component Alternatives Using Multi-Objective Design Space Exploration
This example shows how to identify and analyze combinations of variant components for a System Composer™ model. To identify the optimal combinations, you perform an exhaustive multi-objective design space exploration using sensitivity analysis.
System Composer Model of UAV
Open the root component sdoQuadcopterSCModel
.
mdl = 'sdoQuadcopterSCModel';
archModel = systemcomposer.openModel(mdl);
The sdoQuadcopterSCModel
model is a high-level model of a quadcopter and defines the four components: Frame
, Battery
, CommunicationModule
, and PropulsionModule
(which further consists of the Motor
and Propeller
components). You define the relevant properties of each component, such as the cost and weight, as stereotypes of the components.
The task is to examine and select the combinations resulting from the following four variant components:
Battery
— This component has three options:4-cell
,6-cell
, and8-cell
. A greater number of cells gives the battery more power capacity, but makes it heavier and more expensive. Adjust this choice by using theBatteryChoice
variable.Frame
— This component has three options:Regular
,HeavyDuty
, andExtraHeavyDuty
. The frames rated for heavier duty can sustain higher payloads but are heavier and more expensive. Adjust this choice by using theFrameChoice
variable.Motor
— This component has three options:15W
,20W
, and25W
. Higher wattage motors provide more torque, assuming all motor choices rotate at the same angular velocity, but are heavier and more expensive. Adjust this choice by using theMotorChoice
variable.Propeller
— This component has three options:2-blade
,3-blade
, and4-blade
. A greater number of blades produces more thrust but makes the propeller heavier and more expensive. Adjust this choice by using thePropChoice
variable.
Specify Design Variables
Create a parameter set for the design variables that specify the choice of the variant components. In this example, the design variables are the four discrete model parameters: BatteryChoice
, FrameChoice
, MotorChoice
, and PropChoice
.
paramSet = sdo.getParameterFromModel(mdl,[], ... ["BatteryChoice","FrameChoice","MotorChoice","PropChoice"]);
Specify the permissible values for the design variables. For example, each of the four design variables can independently have one of the three nominal numeric values.
paramSet(1).ValueSet = [1 2 3]; % BatteryChoice paramSet(2).ValueSet = [1 2 3]; % FrameChoice paramSet(3).ValueSet = [1 2 3]; % MotorChoice paramSet(4).ValueSet = [1 2 3]; % PropChoice
Create Design Space of Design Variables
Create a grid space using the parameter set. The grid space characterizes the allowable design variable values and their combinations. To create all combinations of the allowable values for the design variables, set the combination method to exhaustive
.
gs = sdo.GriddedSpace(paramSet);
gs.Options.Method = 'exhaustive';
Use sdo.sample
to create an exhaustive grid space. Store the exhaustive design space in the variable designSpace
.
designSpace = sdo.sample(gs,[]);
Create Evaluation Function
Create an evaluation function that evaluates the UAV design for a given combination of design variables.
Use an anonymous function with one argument that calls the evaluation function.
evalFcn = @(p) DSEEvalFcn(p,archModel);
The function evalFcn
has one input argument that specifies the choice of design variables. It returns the objective values computed by DSEEvalFcn
as a structure.
The DSEEvalFcn
function evaluates these objective fields:
Endurance
— This defines the flying duration of the quadcopter in minutes.Cost
— This defines the total cost of the quadcopter in dollars.NetPayload
— This defines the total payload weight that can be carried by the quadcopter in grams.PayloadOverload
— This defines the difference between the actual payload capacity and the permissible payload of the quadcopter. A positivePayloadOverload
value indicates that the actual payload on the quadcopter is more than its permissible payload limit.
You calculate the objectives for the top-level component by performing a bottom-up iteration over the child components. For each iteration, you calculate the relevant properties of the components from their defined stereotypes and store the properties in a class-based container. You then calculate the objective fields of the top-level component using the stored properties. For more information on this analysis approach, see Class-Based Analysis for Battery Sizing (System Composer).
To examine the DSEEvalFcn
function in more detail, use the type
command.
type DSEEvalFcn
function vals = DSEEvalFcn(paramSet,archModel) % Evaluation function to calculate the objectives and the constraints values % for each combination of design variable values defined in paramSet. % Set the value of the design variables in the model. sdo.setValueInModel(archModel.Name,paramSet); % Use a class-based container to store and calculate the stereotypes of the % of the model. results = QuadOutcomeContainer(paramSet); % Iterate bottom-up over the components using 'computeDSEOutcome' as the % analysis function. archModel.iterate('BottomUp',@computeAnalysisResults,results); % Extract the required properties of the container for output. % Extract properties to be used as objectives. vals.Endurance= results.endurance; vals.NetPayload = results.netPayload; vals.Cost = results.totalCost; % Extract properties to be used as constraints. vals.PayloadOverload = results.payloadOverload; end
Evaluate Designs
Use sdo.evaluate
to evaluate the model for each combination of design variable values. Pass the evaluation function handle and the grid space to the sdo.evaluate
command. Store the results in the objectiveSpace
variable.
objectiveSpace = sdo.evaluate(evalFcn,gs);
Model evaluated at 81 samples.
Determine Feasibility and Dominance of Outcomes
From the set of objectives calculated in the evaluation function, divide the objectives into the objectives to minimize (objectives_minimize
), the objectives to maximize (objectives_maximize
), and the objectives to use as constraints to determine design feasibility (constraint_columns)
.
This example minimizes Cost
, maximizes Endurance
and NetPayload
, and uses the PayloadOverload
field as a constraint to determine feasibility.
objectives_minimize = {'Cost'}; objectives_maximize = {'Endurance','NetPayload'}; constraint_columns = {'PayloadOverload'};
Use sdoEvaluateDSEOutcomes
to evaluate both the feasibility of the outcomes and the dominance between the feasible outcomes. Store the results in the outcomeResults
variable.
outcomeResults = sdoEvaluateDSEOutcomes(objectiveSpace,objectives_minimize, ...
objectives_maximize,constraint_columns);
The sdoEvaluateDSEOutcomes
function takes these input arguments:
Table containing the evaluated objectives
Names of the objectives to minimize
Names of the objectives to maximize
Names of the objectives to use as constraints
The function returns a table with two columns: Feasible
and Dominated
.
The Feasible
column contains information about whether a design outcome is feasible. A design outcome is feasible if its corresponding constraint evaluations are less than or equal to zero for all column names defined in constraint_columns
.
The Dominated
column contains information about whether a design outcome is dominated by other design outcomes. A design outcome is dominated if it exhibits worse performance in at least one minimization or maximization objective and similar performance in the remaining objectives, as compared to another design outcome. Dominated outcomes are not preferred since other outcomes that perform better exist. The design outcomes that are not dominated are called nondominated outcomes. Nondominated outcomes are preferred since they lie on the Pareto frontier. The Pareto frontier is a set of feasible outcomes that achieve the best tradeoff among all the objectives.
To examine the sdoEvaluateDSEOutcomes
function in more detail, see the sdoEvaluateDSEOutcomes.m
file or use the type
command.
type sdoEvaluateDSEOutcomes
function outcomes = sdoEvaluateDSEOutcomes(objectiveData, ... minimizedObjectives,maximizedObjectives, ... constraintColumns) % Evaluates the feasibility of the outcomes and identifies the dominated % outcomes from the set of feasible outcomes. arguments objectiveData table minimizedObjectives = {} maximizedObjectives = {} constraintColumns = {} end % Concatenate all objectives allObjectives = [minimizedObjectives(:)' maximizedObjectives(:)']; % Invert the objectives that need to be maximized for idx = 1:numel(maximizedObjectives) objectiveData.(maximizedObjectives{idx}) = -1*objectiveData.(maximizedObjectives{idx}); end outcomes = table; % Check feasibility outcomes.Feasible = evaluateFeasiblity(objectiveData,constraintColumns); % Check nondominance outcomes.Dominated = evaluateDominance(objectiveData,allObjectives,outcomes.Feasible); end function feasibleIdx = evaluateFeasiblity(data,constraintColumns) % Helper function to evaluate feasibility of an outcome feasibleIdx = true(size(data,1),1); for cIdx=1:numel(constraintColumns) cName = constraintColumns{cIdx}; fIdx = data.(cName)<=0; feasibleIdx = feasibleIdx & fIdx; end end function dominatedIdx = evaluateDominance(data,ObjectiveColumns,feasibleIdx) % Helper function to find the dominated outcomes. arguments data ObjectiveColumns feasibleIdx = true(size(data,1),1) end % Start with all points being nondominant dominantIdx = feasibleIdx; for i = 1:numel(dominantIdx) if ~dominantIdx(i) continue end currentPoint = data{i, ObjectiveColumns}; for j = i:numel(dominantIdx) if ~dominantIdx(j) continue end comparisonPoint = data{j, ObjectiveColumns}; objectiveComparison = currentPoint - comparisonPoint; if any(objectiveComparison>0) && any(objectiveComparison<0) % No point is better continue elseif any(objectiveComparison>0) % Comparison point is better dominantIdx(i) = false; elseif any(objectiveComparison<0) % Current point is better dominantIdx(j) = false; end end end dominatedIdx = ~dominantIdx; end
Examine Nondominated Designs
Concatenate the design data (designSpace
) and the objective data (objectiveSpace
). Store the concatenated table in the variable allData
.
allData = [designSpace objectiveSpace outcomeResults];
Define the fields to show on the plot in the plottedFields
variable.
plottedFields = [designSpace.Properties.VariableNames, ...
objectives_minimize,objectives_maximize];
Use the Dominated
column of outcomeResults
to filter out the dominated designs. Dominated designs are the designs that are inferior to the nondominated designs for at least one objective and exhibit the same performance as the nondominated designs for the remaining objectives.
Create a parallel coordinates plot to examine the mapping between the design space and the objective space for the nondominated designs. Concatenate the design space, the objective space, and the outcome results and pass the concatenated table as an input to the parallelplot
command.
plotData = allData(allData.Dominated==0,:);
DSEPlot = parallelplot(plotData,LineAlpha=0.4);
DSEPlot.CoordinateVariables = [designSpace.Properties.VariableNames, ...
objectives_minimize,objectives_maximize];
All the nondominated (Pareto optimal) design outcomes use the 15W
motor (MotorChoice==1
), indicating that the 15W
motor is a safe motor choice for this exercise. This result is due to the assumption that the system operates on the same angular velocity for all motor alternatives. Because a higher motor power decreases endurance but does not lead to improvement in the payload capacity, a motor with a lower power is preferable.
None of the nondominated design outcomes use the Regular
frame (FrameChoice==1
), indicating that you can eliminate the Regular
frame from the choice of frame variants for the quadcopter. The use of a Regular
frame results in a lower permissible payload capacity, which either renders the quadcopter design infeasible or greatly reduces the payload capacity of the quadcopter.
Examine Feasible Designs
Use the Feasible
column of the outcomeResults
to filter out the infeasible designs.
Update the parallel plot source table to show the filtered data.
plotData = allData(allData.Feasible==0,:); DSEPlot.SourceTable = plotData;
Set the GroupVariable
property of DSEPlot
to group the design outcomes by propeller choice.
DSEPlot.GroupVariable = "PropChoice";
As you group the design outcomes by choice of the propeller, the outcomes also form a grouped spectrum on the NetPayload
axis, indicating that the choice of propeller highly influences the net payload capacity of the quadcopter. You can choose the propeller based on the desired net payload capacity value, independent of choices for the other components.
Summary
This example demonstrates an approach to perform a static multi-objective design space exploration on components when the design details (such as Simulink® models) are not available. Use the approach presented in this example to identify feasible designs, explore performance tradeoffs, and select variant alternatives in the early stages of design.
See Also
sdo.evaluate
| sdo.getParameterFromModel
| sdo.GriddedSpace
| sdo.sample