• Keine Ergebnisse gefunden

5.5 Selection Algorithm

5.5.2 Algorithms

In the following, three iterations of the algorithm to solve the problem is presented. The three versions are described on a high level to illustrate the operation of the search pro-cess. A more detailed representation of the implemented recursive backtracking algorithm is shown at the end of this section.

Algorithm 1: Straightforward Search

The first version of the algorithm follows the fundamental notion of model based com-position. That algorithm has never been implemented due to its obvious inefficiency.

However, it provides a first insight in the general practical property propagation and assessment.

1. For all compositionsc

2. Ifcis structurally complete

3. Assess the effect of the Composition properties in the WM 4. If it solves all conflicts in the WM

5. A suitable composition has been found

The realization of this algorithm is straightforward: The CCG generates the component compositions. The properties and relations of the compositions are forwarded to the PRG. In the PRG the validity of the composition is assessed and a binary answer is returned to the CCG.

Algorithm 2: Respecting the Structural Dependencies of the System

The inefficiency of Algorithm 1 is caused by the fact that the search iterates through all possible compositions regardless of the actual structure of the composition. This al-gorithm can be optimized by exploiting the reachability requirement of the CCG. This means only components are considered that may be attached to the system under devel-opment.

The adapted algorithm is:

1. While compositionC not complete

2. Find a component cin the Repository that may be attached to C.

3. Addc to the compositionC 4. Ifc is structurally complete

5. Assess the effect of the composition properties in the WM 6. If it solves all conflicts in the WM

7. A suitable composition has been found

8. If noccould be found: remove last added component and continue search (backtrack)

This algorithm can be implemented by disabling all components for selection at the beginning. Components are only selectable if they solve a specific need.

From structural point of view, the only open demand can be either open interfaces or abstract components without implementation. So at any point in the composition process we maintain the sets of open interfaces IO or abstract componentsCO.

These lists already allow the implementation of an optimization. After adding a component c, with the mandatory interfaces Ic used by c (Ic =c×Tcu), the solvability of i can be checked by verifying that ∀i ∈ Ic : i×Ti×Tcp 6= ∅. If for one interface no component can be found, it is clear that c can never be completely implemented in the current context of the application. A similar check can be performed on open components.

With the knowledge that the current composition with componentcis not implementable the algorithm can backtrack immediately.

While, generally, we follow a depth-first backtracking, the completability check is a one-level breadth-first test. It controls the search space for the entire subtree, and thus identifies non-solvable configurations before starting a deep backtrack. This operation is an extension of step 2 of the algorithm.

Algorithm 3: Respecting the Semantic Dependencies

The first two versions of the algorithm checked the properties of the system only after a composition was complete. This is not the best solution since it can be assumed that many configurations and components can be ruled out early due to behavioral incompatibilities.

For instance a cryptographic implementation that uses assembler code to improve the performance only runs on specific microcontrollers. If the application demands a different microcontroller, the conflicting cryptographic component can be ruled out for the entire selection process. We avoid such a dedicated filtering process. Instead, we introduce a concept to identify such static conflicts automatically.

The basic idea is to update the PRG of the WM after every component that has been added to the CCG. The new component may cause conflicts in the PRG. A conflict is a violation of a constraint. Such conflicts may be static or resolvable.

Resolvable conflicts are constraint relations of the PRG which are false in the moment of evaluation, while they may change in further configuration process.

Static conflicts are constraint violations in the PRG which cannot be solved with ad-ditional components or settings.

A conflictf is static if:

∀n∈(f ×E−∗) : (n×E−16=∅) OR (nis defined),

meaning that for all nodesn of the PRG for which the constraint f depends on, eitherndepends on other nodes or the node is defined (either by a requirement or a component property). If that is the case,f cannot be resolved in the future.

Practically, it can be solved by forwarding a ’static’ flag in the PRG. A property is static if it cannot be changed in the further process. Consequently, the result of a relation with all inputs defined as static is static too.

As result the main iteration of the algorithm is changed as follows:

1. While compositionC not complete

2. Find a component cin the Repository that may be attached to C.

3. Addc to the compositionC

4. Assess the effect of the composition properties in the WM 5. IfC causes static conflicts

6. removecand backtrack 7. Ifc is structurally complete

8. If it solves all conflicts in the WM

9. A suitable composition has been found

10. If noccould be found: remove last added component and continue search (backtrack)

This algorithm adds the steps 4 to 6 to assess the semantics of the composition, while the rest of the algorithm is still equivalent to algorithm version 2. Also this version can be optimized by the breadth-first test during step 2. With the additional coverage of semantic attributes in the WM it immediately filters out all components not suitable for the active system. For example the cryptographic implementation that conflicts the pre-selected hardware will be identified during the first iteration and never be considered again.

This test can be exploited also to gather which component may affect the PRG the most. Naturally we want to integrate components first that affect many aspects of the system instead of peripheral services. This optimization is respected in the actually implemented algorithm as it is presented in the following.

Final Selection Algorithm

The third version of the algorithm finally was implemented as recursive backtracking algorithm. Its core is a recursive function to add a component to a given interface. The function updates the PRG and the CCG, identifies complete composition, detects con-flicts and iterates through suitable components to complete the composition.

It is presumed that the backtracking from the function restores the content of all vari-ables and structures, including PRG and CCG.

Beside the component repository, the algorithm maintains two sets of selectable compo-nents:

SC - Selectable Components is a subset of the component repository containing only the components which may be used for the composition. This set contains all components that are not ruled out due to conflicts.

AC - Active Components is a subset of the SC, containing only the components that can be attached to the current system under development. If a new component is added to the system, other components may be added to the AC (due to new needed interfaces) or removed from the AC (since interfaces are satisfied by the new component).

function bool recurs add (component c, interface i, PRG, CCG) 1. Add component to CCG and PRG and check conflicts

• if PRG.conflicts = 0 then solution found (CCG), return true

• if PRG.static conflicts>0 then return false

2. update actively selectable set of components and open interfaces

• add all components in the selectable set (SC) that provide one interface usable byc

– ∀c2 : c2∈SC∧(c×TCU×TI)∩(c2×TCP−1)6=∅: AC.add(c2)

• test all elements in AC on compatibility to current configuration, and remove conflicting components

– if∀c2∈AC : PRG.compatible(c2.PRG) = false or CCG.compatible(c2.PRG) = false then

SC.delete (c2); AC.delete (c2);

– else record the number of changed properties for the interfaces of all c2

• if the remaining active set of components is not sufficient to satisfy the open interfaces: backtrack

– return false

3. if c is a non-implementable component look for implementations

• functionreplace removes c2 and calls recurs add to add c – replace (c2, c)

4. select interfaceiwith the highest average number of changes in the PRG

• test setT S

• For∀c2∈T S: recurs add(c2, i)

The algorithm has several notable properties:

Resolves abstract interfaces: Abstract interfaces are resolved in the first substep of Step 2. The equation c2 ∈ AC∧(c×TCU ×TI)∩(c2×TCP−1)6=∅ addresses all components c2 from the set of selectable components which provide at least one interface that is compatible to a used interface of the new componentc.

Resolves abstract components in step 3. There the abstract component is replaced by the corresponding implementation.

Evaluates the properties of the composition immediately. Therefore it is apply-ing the PRG with its complex models.

Discovers and evaluates conflicts early: In Step 1 conflicts with the CCG and PRG are evaluated by adding the new component to the graphs. After adding they re-port the conflicts.

Additionally, within Step 2 all selectable components are tested on their compati-bility. In case of incompatibility the latest added component will be removed from the set of selectable components (SC), which immediately reduces the search space.

Maintains only selectable components that can be added in the data structure AC and SC.

Terminates: In step 1, if a configuration with no open structural dependencies (IO = CO =∅) and no semantic conflicts (PRG.conflicts>0) is found, the configuration is stored within the solution found subroutine.