# 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`

, and`8-cell`

. A greater number of cells gives the battery more power capacity, but makes it heavier and more expensive. Adjust this choice by using the`BatteryChoice`

variable.`Frame`

— This component has three options:`Regular`

,`HeavyDuty`

, and`ExtraHeavyDuty`

. The frames rated for heavier duty can sustain higher payloads but are heavier and more expensive. Adjust this choice by using the`FrameChoice`

variable.`Motor`

— This component has three options:`15W`

,`20W`

, and`25W`

. 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 the`MotorChoice`

variable.`Propeller`

— This component has three options:`2-blade`

,`3-blade`

, and`4-blade`

. A greater number of blades produces more thrust but makes the propeller heavier and more expensive. Adjust this choice by using the`PropChoice`

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 positive`PayloadOverload`

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`