Skip to content

Structured Random Design

Felix Dobslaw edited this page Jun 30, 2013 · 19 revisions

Structural Designs

After getting to know the concept of structural parameters and code mappings, we will in this tutorial give some examples of combining structural and numeric parameters in one design, especially with respect to parameter hierarchies.

Combining Numeric and Structured Parameters

Using InPUT makes most sense when having multiple parameters and when they are a combination of structural and numeric ones. The design space for the JUnit tests contains all kinds of parameter definitions. A valid exported design is here. Here is the respective code mapping and in here you find the model classes. InPUT is non-invasive, none of the model classes require any InPUT specific interface or the like. By solely changing the code mapping, they could be exchanged by other means of implementation.

Enum Mapping

Given the first structural example

	<SParam id="Decision">
		<SChoice id="FirstChoice"/>
		<SChoice id="SecondChoice"/>
		<SChoice id="ThirdChoice"/>
	</SParam>

there is nothing said about how Decision is implemented, nor it's choices. A valid alternative to the presented mapping in the former tutorial is to create an enum:

public enum Decision {
     FIRST,SECOND,THIRD;
}

and define the mapping as in

	<Mapping id="Decision" type="model.Decision" />
	<Mapping id="Decision.FirstChoice" type="FIRST" />
	<Mapping id="Decision.SecondChoice" type="SECOND" />
	<Mapping id="Decision.ThirdChoice" type="THIRD" />

As a consequence, the parameter is now treated as an enumeration type.

Structural Parameter Arrays

Also structural parameters can be specified as array types. The only difference to numeric array definitions is that the type String does not contain a primitive datatype. Examples:

	type="[10][2]"  // two dimensional array with ten rows and two columns
	type="[2][]"  // two dimensional array with two rows and user defined amount of columns
	type="[]"  // one dimensional array with user defined amount of columns

Each unspecified dimension will in a random design lead to a the default number of entries, 1.

Parameter Hierarchies

At times, we deal with parameters that carry along sub-parameters. For evolutionary algorithms, a typical example might be the tournament size for the tournament selection method. InPUT allows for structural parameters to contain sub-parameters of both, numeric, and structural nature. As a consequence, parameter descriptors can become arbitrary tree structures (see example on start page).

The parameters have to fulfill a contract in order to allow calls for arbitrary Java objects like this

	MyAlgorithm a = design.getValue("MyAlgorithm");

This, because sub-parameters have to be injected into the objects using reflection mechanisms, and those mechanisms require handles for constructors or setter methods, given by a user. However, the contract does not require any changes in your code, such as the extension of an interface or abstract class. Thus, an injector has to be specified for each sub-parameter. Further, in order for InPUT to gain access to the whole parameter tree given a variable as this

	design.setValue("MyAlgorithm", a2);

user defined getters have to be specified that extracts the parameters recursively from the tree.

Code Mapping: Get & Set Injection

By default, InPUT assumes for each parameter "Parent" with a sub-parameter "Sub" to contain a setter method of name "setSub" and a getter "getSub" with the appropriate types according to the mapping type definition in "Sub" in the "Parent" class. However, the name can be customized in the mapping as in

	<Mapping id="Parent.Sub" type="my.Subclass" get="theRealGetterName" set="theReadSetterName">

For primitive types and String no type attribute shall exist. In cases where the value is a calculated one or derived and set from within the class, the set attribute can be set to false using set="false". Still, setter injection can be accompanied or substituted by constructor injection.

Code Mapping: Constructor Injection

Often we wish to set the field members of an object at the time of creation. Parameters are passed via the constructor, making the constructor an alternative way of injecting sub-parameter values. Where that is the case, the constructor attribute can be used in the mapping to point the constructor to those sub-parameters in the given order, in which they are to be expected in the constructor call, e.g.:

	<Mapping id="Parent" type="my.ParentClass" constructor="Sub">

tells InPUT that the sub-parameter "Sub" is the first and only argument of the constructor, and that injection neglects the setter attribute of "Sub". Further parameters can be added, using a space in between them:

	<Mapping id="Parent" type="my.ParentClass" constructor="Sub Sub2 Sub3">

One correct Constructor order has to be held. A parameter that contains another parameter within a design space as a formal parameter for a constructor can also be referred to in the constructor definition with the fully qualified parameter ids in combination with sub parameters:

	<Mapping id="Parent" type="my.ParentClass" constructor="Some.Other.ParamId Sub1">
Summary

In this tutorial we learned how to implement structural parameters. we learned how to define hierarchies and what the code mapping descriptor requires in order to give InPUT full access to all parameters without user intervention or code changes in the user code.

Clone this wiki locally