Detect and Replace Subsystem Clones Programmatically
Clones are modeling patterns that have identical block types and connections. You can refactor your model by creating library blocks from subsystem clones and replacing the clones with links to those library blocks, which enable you to reuse components. For more information about clones, see Enable Component Reuse by Using Clone Detection.
Programmatically checking for clones during the model submission process helps you identify opportunities to reuse subsystems before the model is deployed into the main product branch. When updating your model, you can use the Clone Detector app and clone detector API simultaneously. When you use the clone detector API, the detected clones appear in the Simulink® Editor.
This example shows how to use the clone detection APIs to identify and replace clones in a single model by creating a library file with subsystem blocks and replacing the clones with links to blocks in the library file.
In this example, you learn how to use:
- Simulink.CloneDetection.findClones to find clones in a model. 
- Simulink.CloneDetection.replaceClones to replace clones in a model. 
- Simulink.CloneDetection.checkEquivalency to check the equivalency of the updated model with the original model. 
- Simulink.CloneDetection.Settings to add conditions to the - findClonesoperation.
- Simulink.CloneDetection.ReplacementConfig to add conditions to the - replaceClonesoperation.
Programmatically Identify Clones in a Model
- Open the model - ex_detect_clones_B.- openExample('ex_detect_clones_B');- Save the model in the current working directory. 
- To find subsystem clones, use the function - Simulink.CloneDetection.findClones(). This function creates an object called- cloneResults.- cloneResults = Simulink.CloneDetection.findClones('ex_detect_clones_B')- cloneResults = Results with properties: Clones: [1×1 struct] ExceptionLog: ''- The - cloneResultsobject has- Clones, which is a structure with two fields,- Summaryand- CloneGroups.- cloneResults.Clones - ans = struct with fields: Summary: [1×1 struct] CloneGroups: [1×2 struct]
- View the - Summaryfield.- cloneResults.Clones.Summary - ans = struct with fields: CloneGroups: 2 SimilarClones: 5 ExactClones: 0 Clones: 5 PotentialReusePercentage: [1×1 struct]- In this example, the model has two - CloneGroupswith matching subsystem patterns, five- SimilarClones, and zero- ExactClones, and the five subsystem- Clones.
- View the - CloneGroupsfield.- cloneResults.Clones.CloneGroups - ans = 1×2 struct array with fields: Name Summary CloneList- The model in this example returns an array of two - CloneGroups. Each array includes the- Name,- Summaryand- CloneList.
- View the details of first clone group. - cloneResults.Clones.CloneGroups(1) - ans = struct with fields: Name: 'Similar Clone Group 1' Summary: [1×1 struct] CloneList: {3×1 cell}
- View the - Summary.- cloneResults.Clones.CloneGroups(1).Summary - ans = struct with fields: ParameterDifferences: [1×1 struct] Clones: 3 BlocksPerClone: 8 CloneType: 'Similar' BlockDifference: 1
- View the - CloneListof the first CloneGroup.- cloneResults.Clones.CloneGroups(1).CloneList - ans = 3×1 cell array {'ex_detect_clones_B/Subsystem1'} {'ex_detect_clones_B/Subsystem2'} {'ex_detect_clones_B/Subsystem3'}- Similarly, You can find the results of other - CloneGroupsusing the above steps.
Programmatically Replace Clones in a Model
- To replace clones in a model, use the function - Simulink.CloneDetection.replaceClones(). This function uses the- cloneResultsobject from the- findClonesfunction.- cloneReplacementResults = Simulink.CloneDetection.replaceClones(cloneResults) - cloneReplacementResults = ReplacementResults with properties: ReplacedClones: [1×5 struct] ExcludedClones: {}- The - cloneReplacementResultsobject includes two properties,- ReplacedClonesand- ExcludedClones.
- View the contents of - ReplacedClonesproperty.- cloneReplacementResults.ReplacedClones - ans = 1×5 struct array with fields: Name ReferenceSubsystem- The 1-by-5 array indicates that the function replaced five subsystem clones in the model. 
- View the list of replaced subsystem clones. - struct2table(cloneReplacementResults.ReplacedClones) - ans = 5×2 table Name ReferenceSubsystem ___________________________________ _____________________________ {'ex_detect_clones_B/Subsystem1'} {'newLibraryFile/Subsystem1'} {'ex_detect_clones_B/Subsystem2'} {'newLibraryFile/Subsystem1'} {'ex_detect_clones_B/Subsystem3'} {'newLibraryFile/Subsystem1'} {'ex_detect_clones_B/SS3' } {'newLibraryFile/SS1' } {'ex_detect_clones_B/SS4' } {'newLibraryFile/SS1' }
Identify Clones Using Library Reference Blocks
- Save the model and library file in the current working directory. - ex_detect_clones_E clones_library 
- Use the - Simulink.CloneDetection.Settings()class to create an object that specifies certain conditions for finding clones in a model.- cloneDetectionSettings = Simulink.CloneDetection.Settings() - cloneDetectionSettings = Settings with properties: IgnoreSignalName: 0 IgnoreBlockProperty: 0 ExcludeModelReferences: 0 ExcludeLibraryLinks: 0 ExcludeInactiveRegions: 0 SelectedSystemBoundary: '' DetectClonesAcrossModel: 0 FindClonesRecursivelyInFolders: 1 ParamDifferenceThreshold: 50 ReplaceExactClonesWithSubsystemReference: 0 Libraries: {} Folders: {}
- Set the - ParamDifferenceThresholdparameter. This parameter specifies the number of differences that subsystems must have to be considered clones.- cloneDetectionSettings.ParamDifferenceThreshold = 0 - cloneDetectionSettings = Settings with properties: IgnoreSignalName: 0 IgnoreBlockProperty: 0 ExcludeModelReferences: 0 ExcludeLibraryLinks: 0 ExcludeInactiveRegions: 0 SelectedSystemBoundary: '' DetectClonesAcrossModel: 0 FindClonesRecursivelyInFolders: 1 ParamDifferenceThreshold: 0 ReplaceExactClonesWithSubsystemReference: 0 Libraries: {} Folders: {}- A value of 0 indicates the subsystems must be identical. 
- Add a reference library file to use to match the clone patterns in the - cloneDetectionSettingsobject. In this example,- SSL1and- SSL2are subsystem patterns in the library- clones_library.- cloneDetectionSettings = cloneDetectionSettings.addLibraries('clones_library')- cloneDetectionSettings = Settings with properties: IgnoreSignalName: 1 IgnoreBlockProperty: 0 ExcludeModelReferences: 0 ExcludeLibraryLinks: 0 ExcludeInactiveRegions: 0 SelectedSystemBoundary: '' DetectClonesAcrossModel: 0 FindClonesRecursivelyInFolders: 1 ParamDifferenceThreshold: 50 ReplaceExactClonesWithSubsystemReference: 0 Libraries: {'C:\Users\Examples\clones_library.slx'} Folders: {}
- To find clones, execute the function - Simulink.CloneDetection.findClones()using the model name and- cloneDetectionSettingsobject.- cloneResults = Simulink.CloneDetection.findClones('ex_detect_clones_E', cloneDetectionSettings)- cloneResults = Results with properties: Clones: [1×1 struct]- cloneResults.Clones.Summary - ans = struct with fields: CloneGroups: 2 SimilarClones: 5 ExactClones: 0 Clones: 5 PotentialReusePercentage: [1×1 struct]- In this example, the model has two - CloneGroups, five- SimilarClones, zero- ExactClones, and five subsystem- Clones.
- View the details of first - CloneGroup.- cloneResults.Clones.CloneGroups(1) - ans = struct with fields: Name: 'clones_library/SSL1' Summary: [1×1 struct] CloneList: {3×1 cell}
Replace Clones with Conditions
- 1. To specify conditions for - replaceClonesfunction, create a handle using the- Simulink.CloneDetection.ReplacementConfig()class:- cloneReplacementConfig = Simulink.CloneDetection.ReplacementConfig() - cloneReplacementConfig = ReplacementConfig with properties: LibraryNameToAddSubsystemsTo: 'newLibraryFile' IgnoredClones: {}
- Add subsystems to the - IgnoredCloneslist. In this example, ignore- Subsystem1to avoid replacing it with a clone.- cloneReplacementConfig.addCloneToIgnoreList('ex_detect_clones_E/Subsystem1')- ans = ReplacementConfig with properties: LibraryNameToAddSubsystemsTo: 'newLibraryFile' IgnoredClones: {'ex_detect_clones_E/Subsystem1'}
- To replace clones, use the - replaceClonesfunction with- cloneResultsand- cloneReplacementConfigas the input arguments.- cloneReplacementResults = Simulink.CloneDetection.replaceClones(cloneResults, cloneReplacementConfig) - cloneReplacementResults = ReplacementResults with properties: ReplacedClones: [1×4 struct] ExcludedClones: [1×1 struct]
- View the - ReplacedClonesproperty.- struct2table(cloneReplacementResults.ReplacedClones) - ans = 4×2 table Name ReferenceSubsystem ___________________________________ __________________ {'ex_detect_clones_E/SS3' } {'clones_library/SSL1'} {'ex_detect_clones_E/SS4' } {'clones_library/SSL1'} {'ex_detect_clones_E/Subsystem1'} {'clones_library/SSL2'} {'ex_detect_clones_E/Subsystem2'} {'clones_library/SSL2'}- The - SSL1and- SSL2Reference Subsystem blocks from the reference library replaced the subsystem clones in the model.
- View the - ExcludedClonesproperty.- struct2table(cloneReplacementResults.ExcludedClones) - ans = 1×2 table Name ReferenceSubsystem ___________________________________ __________________ {'ex_detect_clones_E/Subsystem1'} {'unselected'}
Check the Equivalency of the Model
You can check if the updated model is equivalent with the original model by using the
                Simulink.CloneDetection.checkEquivalency() function. This
            function uses Simulink Test Manager to compare the simulation results of the saved
            original model with the updated model and saves the results in the
                checkEquiResults handle.
checkEquiResults = Simulink.CloneDetection.checkEquivalency(cloneReplacementResults)
[21-Dec-2020 16:35:13] Running simulations...
[21-Dec-2020 16:35:32] Completed 1 of 2 simulation runs
[21-Dec-2020 16:35:33] Completed 2 of 2 simulation runs
checkEquiResults = 
  EquivalencyCheckResults with properties:
    List: [1×1 struct]
View the check equivalence results.
checkEquiResults.List
ans = 
  struct with fields:
    IsEquivalencyCheckPassed: 1
               OriginalModel: 'm2m_ex_detect_clones_E/snapshot_2020_12_21_16_35_06_ex_detect_clones_E.slx'
                UpdatedModel: 'ex_detect_clones_E.slx'
The property IsEquivalencyCheckPassed is 1, which suggests that the
            models are equivalent. The OriginalModel and
                UpdatedModel properties show which models the function
            checked.