Generation of designs ===================== The Orthogonal Array package can be used to generate several classes of arrays and designs. A collection of arrays and designs generated by the package is available on the website http://www.pietereendebak.nl/oapackage/index.html. Generation of orthogonal arrays ------------------------------- A list of arrays in LMC form (i.e., lexicographically minimum in columns) can be extended to a list of arrays in LMC form with one additional column. Details about the algorithm are described in :cite:`Eendebak2009`. The main function for array extension is the function :cpp:func:`extend_arraylist`. The arguments for this function are the list of arrays to extend, a specification of the class of arrays in :cpp:class:`arraydata_t` and the options :cpp:class:`OAextend` for the algorithm. An example of a session that extends an array is: .. doctest:: >>> import oapackage >>> nrows=8; ncols=3; >>> arrayclass=oapackage.arraydata_t(2, nrows, 2, ncols) >>> root_array=arrayclass.create_root() >>> root_array.showarraycompact() 00 00 01 01 10 10 11 11 >>> array_list=oapackage.extend_array(root_array, arrayclass) >>> print('found %d extensions of the root array' % len(array_list)) found 2 extensions of the root array A more detailed example is included in :ref:`Enumerate orthogonal arrays`. Conference designs ------------------ A conference design is an :math:`N\times k` matrix with entries 0, -1, +1 such that i) in each column the symbol 0 occurs exactly one time and ii) all columns are orthogonal to each other. For details on conference designs, see the section :ref:`Properties of conference designs` and :cite:`Schoen2018dsd`. An example of a session to generate conference designs is the following: .. admonition:: Generate conference designs with 8 rows .. doctest:: >>> import oapackage >>> conference_class=oapackage.conference_t(8, 6, 0) >>> array = conference_class.create_root_three_columns() >>> array.showarray() array: 0 1 1 1 0 -1 1 1 0 1 1 1 1 1 -1 1 -1 1 1 -1 1 1 -1 -1 >>> l4=oapackage.extend_conference ([array], conference_class, verbose=0) >>> l5=oapackage.extend_conference ( l4, conference_class, verbose=0) >>> l6=oapackage.extend_conference ( l5, conference_class, verbose=0) >>> print('number of non-isomorphic conference designs with 6 columns: %d' % len(l6) ) number of non-isomorphic conference designs with 6 columns: 11 An example notebook with more functionality is included in :ref:`Generation and analysis of conference designs`. The full interface for conference designs is available in the :ref:`Interface for conference designs`. The main functions to extend conference and double conference designs are :cpp:func:`extend_conference` and :cpp:func:`extend_double_conference`, respectively. The low-level functions for generating candidate extension columns of conference and double conference designs are :cpp:func:`generateConferenceExtensions` and :cpp:func:`generateDoubleConferenceExtensions`, respectively. The conference designs are generated in :ref:`LMC0 ` form. Calculation of D-efficient designs ---------------------------------- D-efficient designs (sometimes called D-optimal designs) can be calculated with the function :py:meth:`oapackage.Doptim.Doptimize`. This function uses a coordinate-exchange algorithm to generate designs with good properties for the :math:`D`-efficiency. With the coordinate-exchange algorithm, the following target function :math:`T` is optimized: .. math:: T = \alpha_1 D_{\text{eff}} + \alpha_2 D_{s, \text{eff}} + \alpha_3 D_{1, \text{eff}} Here, :math:`\alpha` is a weight vector specified by the user. Details on the :math:`D_{\text{eff}}`, :math:`D_{s, \text{eff}}` and :math:`D_{1, \text{eff}}` can be found in the section :ref:`Optimality criteria for D-efficient designs`. A Python script to generate D-efficient designs with 40 runs and 7 factors is shown below. .. admonition:: Example of Doptimize usage .. testsetup:: import oapackage oapackage.seedfastrand(123) oapackage.set_srand(123) .. doctest:: >>> N=40; s=2; k=7; >>> arrayclass=oapackage.arraydata_t(s, N, 0, k) >>> print('We generate optimal designs with: %s' % arrayclass) We generate optimal designs with: arrayclass: N 40, k 7, strength 0, s {2,2,2,2,2,2,2}, order 0 >>> alpha=[1,2,0] >>> scores, dds, designs, ngenerated = oapackage.Doptimize(arrayclass, nrestarts=40, optimfunc=alpha, selectpareto=True, verbose=0) Doptimize: iteration 0/40 Doptimize: iteration 39/40 >>> print('Generated %d designs, the best D-efficiency is %.4f' % (len(designs), dds[:,0].max() )) Generated 10 designs, the best D-efficiency is 0.9198 The parameters of the :meth:`~oapackage.Doptim.Doptimize` function are documented in the code. To calculate the :math:`D`-, :math:`D_s`- and :math:`D_1`-efficiencies of the designs, we can use the method :cpp:func:`Defficiencies`. For details on these efficiencies, see the section :ref:`Optimality criteria for D-efficient designs` and :cite:`EendebakSO`. In :cite:`EendebakSO`, it is shown that one can optimize a linear combination of the :math:`D`-efficiency and :math:`D_s`-efficiency to generate a rich set of good compromise designs. From the generated designs, the optimal ones according to Pareto optimality can be selected. .. figure:: images/motivating-40-d-2-2-2-2-2-2-2-scatterplot-ndata2.png Scatterplot for the :math:`D`-efficiency and :math:`D_s`-efficiency for generated designs in :math:`{\operatorname{OA}(40; 2; 2^7)}`. The Pareto optimal designs are colored, while the non-Pareto optimal designs are grey. For reference the strength-3 orthogonal array with highest D-efficiency is also included in the plot. Even-odd arrays --------------- The even-odd arrays are a special class of orthognal arrays with at least one of the odd :math:`J_k`-characteristics unequal to zero. More information on this class of designs will appear later.