Main Content

Create and Analyze Random Schedules for a Model Using the Schedule Editor API

This example uses the Schedule Editor API to perform operations on the schedule. Then it uses a function to generate random schedules and analyze them in Simulation Data Inspector

Open the Model and Get the Schedule Object

Open a model of a Throttle Position Control system and use get_param to obtain the simulink.schedule.OrderedSchedule object. This object contains the current schedule.

model = 'ScheduleEditorAPIWithSubsystemPartitions';
open_system(model);
schedule = get_param(model, 'Schedule')
schedule = 

  OrderedSchedule with properties:

           Order: [9x3 table]
    RateSections: [3x1 simulink.schedule.RateSection]
          Events: [0x1 simulink.schedule.Event]
     Description: ''

Examine the Schedule Object

The schedule object has an Order property that contains the execution order of the partitions in the model. The Order property displays a table that contains partition names, their index, type, and their trigger.

schedule.Order
ans =

  9x3 table

                          Index      Type      Trigger
                          _____    ________    _______

    Cont                    1      Periodic    "0"    
    TPSSecondaryRun5ms      2      Periodic    "0.005"
    MonitorRun5ms           3      Periodic    "0.005"
    ControllerRun5ms        4      Periodic    "0.005"
    ActuatorRun5ms          5      Periodic    "0.005"
    D2                      6      Periodic    "0.005"
    D3                      7      Periodic    "0.01" 
    APPSnsrRun              8      Periodic    "0.01" 
    TPSPrimaryRun10ms       9      Periodic    "0.01" 

Use the index variable in the Order table to change the execution order of the model

schedule.Order.Index('ActuatorRun5ms') = 2;
schedule.Order
ans =

  9x3 table

                          Index      Type      Trigger
                          _____    ________    _______

    Cont                    1      Periodic    "0"    
    ActuatorRun5ms          2      Periodic    "0.005"
    TPSSecondaryRun5ms      3      Periodic    "0.005"
    MonitorRun5ms           4      Periodic    "0.005"
    ControllerRun5ms        5      Periodic    "0.005"
    D2                      6      Periodic    "0.005"
    D3                      7      Periodic    "0.01" 
    APPSnsrRun              8      Periodic    "0.01" 
    TPSPrimaryRun10ms       9      Periodic    "0.01" 

Any moves within the Order property that are made to modify the schedule should result in valid schedule. To perform the schedule modifications and valid moves easier, each partition is grouped with partitions of the same rate in the RateSections property. Each element of the RateSection property contains an order table with partitions of the same rate.

schedule.RateSections(2)
schedule.RateSections(2).Order
ans = 

  RateSection with properties:

     Rate: "0.005"
    Order: [5x3 table]


ans =

  5x3 table

                          Index      Type      Trigger
                          _____    ________    _______

    ActuatorRun5ms          2      Periodic    "0.005"
    TPSSecondaryRun5ms      3      Periodic    "0.005"
    MonitorRun5ms           4      Periodic    "0.005"
    ControllerRun5ms        5      Periodic    "0.005"
    D2                      6      Periodic    "0.005"

Use the index variable to move the partitions within RateSections.

schedule.RateSections(2).Order.Index('ActuatorRun5ms') = 5;
schedule.Order
ans =

  9x3 table

                          Index      Type      Trigger
                          _____    ________    _______

    Cont                    1      Periodic    "0"    
    TPSSecondaryRun5ms      2      Periodic    "0.005"
    MonitorRun5ms           3      Periodic    "0.005"
    ControllerRun5ms        4      Periodic    "0.005"
    ActuatorRun5ms          5      Periodic    "0.005"
    D2                      6      Periodic    "0.005"
    D3                      7      Periodic    "0.01" 
    APPSnsrRun              8      Periodic    "0.01" 
    TPSPrimaryRun10ms       9      Periodic    "0.01" 

Create a Function to Generate Random Schedules

In this section, we create three different functions: randomSchedule, generateSimulationInputs and simulateRandomSchedules

randomSchedule function is used to create random schedules by using random permutations of index modifications in the schedule object. Using the Order and the RateSections properties of the schedule object, partitions in the schedules are moved around in different, random combinations. With these randomly created schedules, models are simulated and compared to study the effect of different schedules on simulation. In the function randomSchedule, the input is the model name. Then use get_param to obtain the simulink.schedule.OrderedSchedule object of the model. The schedule object and its properties are used to modify and randomize the schedules. Create a variable firstExecutionOrder for the first rate section of the model. The rateSections(1).ExecutionOrder = [firstExecutionOrder(1,:); reSchedule(firstExecutionOrder(2:end,:))] line of code calls the function reSchedule which creates random permutations of the indexes.

type randomSchedule
function schedule = randomSchedule(model)
    % schedule = randomSchedule(model) Produces a
    % simulink.schedule.OrderedSchedule that has a randomized permutation
    % of the model's original execution order schedule
    
    arguments
        model char = bdroot
    end
    
    schedule = get_param(model, 'Schedule');
    
    rateSections = schedule.RateSections;
    firstOrder = rateSections(1).Order;
    
    % This assumes that the slowest discrete rate is at index 1. This may
    % not be the case for all models (ex. JMAAB-B).
    rateSections(1).Order = [firstOrder(1,:); reSchedule(firstOrder(2:end,:))];    
    
    for i=2:length(rateSections)
        rateSections(i).Order = reSchedule(rateSections(i).Order);
    end
    
    schedule.RateSections = rateSections;
end

function out = reSchedule(in)
    numPartitions = height(in);
    in.Index = in.Index(randperm(numPartitions));
    out = in;
end

To analyze the effects of different schedules on the model, simulate the model with the different schedules. In this function, create an array of Simulink.SimulationInput objects. Through this array of Simulink.SimulationInput objects, you can apply the schedules to the model with the setModelParameters method of the Simulink.SimulationInput object.

type generateSimulationInputs
function in = generateSimulationInputs(model, numSimulations)
    % in = generateSimulationInputs(model, numSimulations) Generates
    % numSimulations Simulink.SimulationInput objects each containing a
    % different, randomized execution order schedule
    arguments
        model char = bdroot
        numSimulations double = 10
    end
    
    in(numSimulations) = Simulink.SimulationInput();
    in = in.setModelName(model);
    for idx = 1:numSimulations
        in(idx) = in(idx).setModelParameter('Schedule', randomSchedule(model));
    end
end

In the last function, use the array of Simulink.SimulationInput objects to run multiple simulations. Once the simulations are complete, you can plot the output of all the simulations in Simulation Data Inspector.

type simulateRandomSchedules
function out = simulateRandomSchedules(model, numSimulations)
    % out = simulateRandomSchedules(model, numSimulations) Simulates a 
    % model numSimulations number of times.  Each simulation has a
    % randomized execution order schedule.
    arguments
        model char = bdroot
        numSimulations double = 10
    end
        
    in = generateSimulationInputs(model, numSimulations);
    out = sim(in);
    plot(out);
end

Execute the Functions

Now run the above functions for the ScheduleEditorAPIWithSubsystemPartitions model. First, use the randomSchedule function to create randomly generated schedules, then, use the generateSimulationInputs function to generate an array of Simulink.SimulationInput objects, and use the simulateRandomSchedule function to simulate the model with different schedules and plot their results for comparison. Let's run simulations with 15 randomly generated schedules.

simulateRandomSchedules(model,15)
[13-Feb-2024 00:34:41] Running simulations...
[13-Feb-2024 00:34:50] Completed 1 of 15 simulation runs
[13-Feb-2024 00:34:51] Completed 2 of 15 simulation runs
[13-Feb-2024 00:34:53] Completed 3 of 15 simulation runs
[13-Feb-2024 00:34:54] Completed 4 of 15 simulation runs
[13-Feb-2024 00:34:55] Completed 5 of 15 simulation runs
[13-Feb-2024 00:34:56] Completed 6 of 15 simulation runs
[13-Feb-2024 00:34:56] Completed 7 of 15 simulation runs
[13-Feb-2024 00:34:57] Completed 8 of 15 simulation runs
[13-Feb-2024 00:34:58] Completed 9 of 15 simulation runs
[13-Feb-2024 00:34:59] Completed 10 of 15 simulation runs
[13-Feb-2024 00:34:59] Completed 11 of 15 simulation runs
[13-Feb-2024 00:35:00] Completed 12 of 15 simulation runs
[13-Feb-2024 00:35:01] Completed 13 of 15 simulation runs
[13-Feb-2024 00:35:02] Completed 14 of 15 simulation runs
[13-Feb-2024 00:35:03] Completed 15 of 15 simulation runs

ans = 

1x15 Simulink.SimulationOutput array