Main Content

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);

sdoQuadcopterSCModel

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];

Figure contains an object of type parallelplot.

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";

Figure contains an object of type parallelplot.

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

| | |

Related Topics