* Bug #13421 fixed - Callback functions for genetic algorithms were missing. 85/14585/15
Michael BAUDIN [Wed, 28 May 2014 13:08:38 +0000 (15:08 +0200)]
Now user can set functions to stop iterations and access the population.

Change-Id: Ib70e2fd25f7dc8037daf198a8f20e08bd6a1700a

18 files changed:
scilab/CHANGES_5.5.X
scilab/modules/genetic_algorithms/help/en_US/algorithms/optim_ga.xml
scilab/modules/genetic_algorithms/help/en_US/algorithms/optim_moga.xml
scilab/modules/genetic_algorithms/help/en_US/algorithms/optim_nsga.xml
scilab/modules/genetic_algorithms/help/en_US/algorithms/optim_nsga2.xml
scilab/modules/genetic_algorithms/help/en_US/utilities/output_ga_default.xml [new file with mode: 0644]
scilab/modules/genetic_algorithms/macros/optim_ga.sci
scilab/modules/genetic_algorithms/macros/optim_moga.sci
scilab/modules/genetic_algorithms/macros/optim_nsga.sci
scilab/modules/genetic_algorithms/macros/optim_nsga2.sci
scilab/modules/genetic_algorithms/macros/output_ga_default.sci [new file with mode: 0644]
scilab/modules/genetic_algorithms/macros/output_moga_default.sci [new file with mode: 0644]
scilab/modules/genetic_algorithms/macros/output_nsga2_default.sci [new file with mode: 0644]
scilab/modules/genetic_algorithms/macros/output_nsga_default.sci [new file with mode: 0644]
scilab/modules/genetic_algorithms/tests/nonreg_tests/bug_13421.dia.ref [new file with mode: 0644]
scilab/modules/genetic_algorithms/tests/nonreg_tests/bug_13421.tst [new file with mode: 0644]
scilab/modules/genetic_algorithms/tests/nonreg_tests/bug_8415.dia.ref
scilab/modules/genetic_algorithms/tests/unit_tests/optim_ga.dia.ref

index dd24407..fc287f3 100644 (file)
@@ -119,6 +119,9 @@ Scilab Bug Fixes
 
 * Bug #13420 fixed - mutation_ga_binary did not calculate properly multiple mutations.
 
+* Bug #13421 fixed - Callback functions for genetic algorithms were missing.
+                     Now the user can set functions to stop iterations and access the population.
+
 * Bug #13424 fixed - crossover_ga_binary algorithm was not the classical point crossover one.
                      Also fixed the usage of binary length.
 
index ff05995..6c2a029 100644 (file)
@@ -67,8 +67,9 @@
                 <term>Log</term>
                 <listitem>
                     <para>
-                        if %T, we will display to information message during the run
-                        of the genetic algorithm.
+                        if %T, will call the output function at the end of each
+                        iteration, see <literal>"output_func"</literal> under
+                        <varname>param</varname> variable below.
                     </para>
                 </listitem>
             </varlistentry>
                             <para>
                                 "codage_func": the function which will perform the coding
                                 and decoding of individuals (default function:
-                                coding_ga_identity).
+                                <link linkend="coding_ga_identity">coding_ga_identity</link>).
                             </para>
                         </listitem>
                         <listitem>
                             <para>
                                 "init_func": the function which will perform the
                                 initialization of the population (default function:
-                                init_ga_default).
+                                <link linkend="init_ga_default">init_ga_default</link>).
                             </para>
                         </listitem>
                         <listitem>
                             <para>
                                 "crossover_func": the function which will perform the
                                 crossover between two individuals (default function:
-                                crossover_ga_default).
+                                <link linkend="crossover_ga_default">crossover_ga_default</link>).
                             </para>
                         </listitem>
                         <listitem>
                             <para>
                                 "mutation_func": the function which will perform the
                                 mutation of one individual (default function:
-                                mutation_ga_default).
+                                <link linkend="mutation_ga_default">mutation_ga_default</link>).
                             </para>
                         </listitem>
                         <listitem>
                             <para>
-                                "selection_func": the function whcih will perform the
+                                "selection_func": the function which will perform the
                                 selection of individuals at the end of a generation (default
-                                function: selection_ga_elitist).
+                                function: <link linkend="selection_ga_elitist">selection_ga_elitist</link>).
                             </para>
                         </listitem>
                         <listitem>
                         </listitem>
                         <listitem>
                             <para>
-                                "pressure": the value the efficiency of the worst
+                                "pressure": the value of the efficiency of the worst
                                 individual (default value: 0.05).
                             </para>
                         </listitem>
+                        <listitem>
+                            <para>
+                                "output_func": a callback function called after each
+                                generation if <varname>Log</varname> is %T (default
+                                function <link linkend="output_ga_default">output_ga_default</link>).
+                            </para>
+                        </listitem>
                     </itemizedlist>
                 </listitem>
             </varlistentry>
             <literal>optim_ga</literal> function.
             This flexibility is provided by the various functions which
             can be set in the <literal>param</literal> variable.
-            In order to analyze the header of these functions (i.e.
-            the input and output arguments), we may read the help page
+            The header of these functions (i.e.
+            the input and output arguments), can be checked through the help page
             corresponding to the default function.
             For example, in order to understand what are the input and output arguments of the
-            "codage_func" function, we may read the page of the <literal>coding_identity</literal> function.
+            <literal>"codage_func"</literal> function, please refer to the help page of the <link linkend="coding_ga_identity">coding_identity</link> function.
         </para>
         <para>
-            See in the Demonstrations for more examples for this function.
+            See the Demonstrations for more examples for this function.
         </para>
     </refsection>
     <refsection>
         <para>
             The following session presents the simplest possible example.
             We minimize a quadratic function in dimension 3.
-            By default, all the parameters are taken in the interval 
+            By default, all the parameters are taken in the interval
             [0,1]^3.
-            The "dimension" field is passed to the function which computes the 
-            initial population, which is <literal>init_ga_default</literal> 
+            The "dimension" field is passed to the function which computes the
+            initial population, which is <literal>init_ga_default</literal>
             function by default.
             In the case where the "dimension" field is not customized,
             the default value is used, which is equal to 2.
         </para>
-        <programlisting role="example"><![CDATA[ 
+        <programlisting role="example"><![CDATA[
 function y=f(x)
   y = sum(x.^2)
 endfunction
@@ -222,7 +230,7 @@ ga_params = add_param(ga_params,"dimension",3);
             In the following script, we compute some basic statistics about the
             optimum population and get the best and the worst points.
         </para>
-        <programlisting role="example"><![CDATA[ 
+        <programlisting role="example"><![CDATA[
 // Display basic statistics
 // min, mean and max function values of the population.
 disp([min(fobj_pop_opt) mean(fobj_pop_opt) max(fobj_pop_opt)])
@@ -234,18 +242,31 @@ xmin = pop_opt(k)
 xmax = pop_opt(k)
  ]]></programlisting>
         <para>
-            In the following example, we customize all the options 
+            In the following example, we customize all the options
             in order to show all the features of the algorithm.
         </para>
-        <programlisting role="example"><![CDATA[ 
+        <programlisting role="example"><![CDATA[
+// Objective function
 function y=f(x)
   y = sum(x.^2)
 endfunction
 
+// Output function with a stop criterion
+function stop = output_ga_custom(gen_index, nb_generation, Pop, FObj_Pop, param)
+    [threshold, err] = get_param(param, "threshold", 1E-10); // default value for the threshold
+    printf(_("%s: iteration %d / %d \n"), "optim_ga", gen_index, nb_generation);
+    printf(_("    min / max value found = %.4E / %.4E\n"), min(FObj_Pop), max(FObj_Pop));
+    stop = %f
+    if abs(max(FObj_Pop) - min(FObj_Pop)) < threshold then
+        printf(_("    Stop criterion reached: Delta Max to Min under threshold"));
+        stop = %t
+    end
+endfunction
+
 PopSize     = 100;
 Proba_cross = 0.7;
 Proba_mut   = 0.1;
-NbGen       = 10;
+NbGen       = 20;
 NbCouples   = 110;
 Log         = %T;
 pressure    = 0.05;
@@ -257,18 +278,23 @@ ga_params = add_param(ga_params,"maxbound",[2; 2]);
 ga_params = add_param(ga_params,"dimension",2);
 ga_params = add_param(ga_params,"beta",0);
 ga_params = add_param(ga_params,"delta",0.1);
-// Parameters to fine tune the Genetic algorithm. 
+// Parameters to fine tune the Genetic algorithm.
 // All these parameters are optional for continuous optimization
-// If you need to adapt the GA to a special problem, you 
+// If you need to adapt the GA to a special problem, you
 ga_params = add_param(ga_params,"init_func",init_ga_default);
 ga_params = add_param(ga_params,"crossover_func",crossover_ga_default);
 ga_params = add_param(ga_params,"mutation_func",mutation_ga_default);
 ga_params = add_param(ga_params,"codage_func",coding_ga_identity);
 ga_params = add_param(ga_params,"selection_func",selection_ga_elitist);
+
 //ga_params = add_param(ga_params,"selection_func",selection_ga_random);
 ga_params = add_param(ga_params,"nb_couples",NbCouples);
 ga_params = add_param(ga_params,"pressure",pressure);
 
+// Customized output function with a stop criterion added
+ga_params = add_param(ga_params, "threshold", 1E-6); // User defined parameter for the output function
+ga_params = add_param(ga_params, "output_func", output_ga_custom);
+
 [pop_opt, fobj_pop_opt, pop_init, fobj_pop_init] = ..
   optim_ga(f, PopSize, NbGen, Proba_mut, Proba_cross, Log, ga_params);
  ]]></programlisting>
@@ -276,23 +302,23 @@ ga_params = add_param(ga_params,"pressure",pressure);
     <refsection>
         <title>Customizing the initial population</title>
         <para>
-            In the following example, we customize the init function, 
+            In the following example, we customize the init function,
             which computes the initial population.
-            In the <literal>myinitga</literal> function, we use the grand function 
+            In the <literal>myinitga</literal> function, we use the grand function
             (instead of the default rand used in
             init_ga_default).
-            We could use any other type of population generator, including, 
-            for example, a low discrepancy sequence such as the Halton or Sobol 
+            We could use any other type of population generator, including,
+            for example, a low discrepancy sequence such as the Halton or Sobol
             sequence.
         </para>
-        <programlisting role="example"><![CDATA[ 
+        <programlisting role="example"><![CDATA[
 function y=f(x)
   y = sum(x.^2)
 endfunction
 
 function Pop_init = myinitga ( popsize , param )
   // This message is to be displayed in the console
-  // for demonstration purpose only : 
+  // for demonstration purpose only :
   // remove it in a real application!
   disp("Initializing the Population with grand")
   // We deal with some parameters to take into account
@@ -300,7 +326,7 @@ function Pop_init = myinitga ( popsize , param )
   [Dim,err]       = get_param(param,"dimension",2)
   [MinBounds,err] = get_param(param,"minbound",-2*ones(1,Dim))
   [MaxBounds,err] = get_param(param,"maxbound",2*ones(1,Dim))
-  
+
   // Pop_init must be a list()
   Pop_init = list()
   nr = size(MaxBounds,1)
@@ -334,17 +360,17 @@ ga_params = add_param(ga_params,"init_func",myinitga);
         <para>
             In some cases, the objective function needs additional parameters
             in order to be evaluated.
-            In this case, we can pass a list to the <literal>optim_ga</literal> 
-            function, where the first element of the list is the function and the 
+            In this case, we can pass a list to the <literal>optim_ga</literal>
+            function, where the first element of the list is the function and the
             remaining elements are the extra parameters.
         </para>
         <para>
             This is done in the following script, where the function <literal>f</literal>
             needs the two extra parameters <literal>a1</literal> and <literal>a2</literal>.
-            This is why we define the list <literal>myobjfun</literal> and 
+            This is why we define the list <literal>myobjfun</literal> and
             pass it to the <literal>optim_ga</literal> solver.
         </para>
-        <programlisting role="example"><![CDATA[ 
+        <programlisting role="example"><![CDATA[
 function y = f ( x , a1 , a2 )
   y = a1*sum(x.^2) + a2
 endfunction
index bd27ddd..2969120 100644 (file)
@@ -28,7 +28,7 @@
                     <para>the function to be optimized. The header of the function is
                         the following :
                     </para>
-                    <programlisting role=""><![CDATA[ 
+                    <programlisting role=""><![CDATA[
 y = f(x)
  ]]></programlisting>
                     <para>or</para>
@@ -69,8 +69,10 @@ y = list(f,p1,p2,...)
             <varlistentry>
                 <term>Log</term>
                 <listitem>
-                    <para>if %T, we will display to information message during the run
-                        of the genetic algorithm.
+                    <para>
+                        if %T, will call the output function at the end of each
+                        iteration, see <literal>"output_func"</literal> under
+                        <varname>param</varname> variable below.
                     </para>
                 </listitem>
             </varlistentry>
@@ -81,13 +83,13 @@ y = list(f,p1,p2,...)
                     <itemizedlist>
                         <listitem>
                             <para>'codage_func': the function which will perform the coding
-                                and decoding of individuals (default function: codage_identity).
+                                and decoding of individuals (default function: <link linkend="coding_ga_identity">coding_ga_identity</link>).
                             </para>
                         </listitem>
                         <listitem>
                             <para> 'init_func': the function which will perform the
                                 initialization of the population (default function:
-                                init_ga_default). 
+                                <link linkend="init_ga_default">init_ga_default</link>).
                             </para>
                         </listitem>
                         <listitem>
@@ -99,25 +101,25 @@ y = list(f,p1,p2,...)
                         <listitem>
                             <para> 'crossover_func': the function which will perform the
                                 crossover between two individuals (default function:
-                                crossover_ga_default). 
+                                <link linkend="crossover_ga_default">crossover_ga_default</link>).
                             </para>
                         </listitem>
                         <listitem>
                             <para> 'mutation_func': the function which will perform the
                                 mutation of one individual (default function:
-                                mutation_ga_default). 
+                                <link linkend="mutation_ga_default">mutation_ga_default</link>).
                             </para>
                         </listitem>
                         <listitem>
                             <para> 'selection_func': the function whcih will perform the
                                 selection of individuals at the end of a generation (default
-                                function: selection_ga_elitist). 
+                                function: <link linkend="selection_ga_elitist">selection_ga_elitist</link>).
                             </para>
                         </listitem>
                         <listitem>
                             <para>'nb_couples': the number of couples which will be selected
                                 so as to perform the crossover and mutation (default value:
-                                100). 
+                                100).
                             </para>
                         </listitem>
                         <listitem>
@@ -125,6 +127,13 @@ y = list(f,p1,p2,...)
                                 individual (default value: 0.05).
                             </para>
                         </listitem>
+                        <listitem>
+                            <para>
+                                "output_func": a callback function called after each
+                                generation if <varname>Log</varname> is %T (default
+                                function <literal>output_moga_default</literal>).
+                            </para>
+                        </listitem>
                     </itemizedlist>
                 </listitem>
             </varlistentry>
@@ -172,7 +181,7 @@ y = list(f,p1,p2,...)
     
     <refsection>
         <title>Examples</title>
-        <programlisting role="example"><![CDATA[ 
+        <programlisting role="example"><![CDATA[
 function f = deb_1(x)
    f1_x1 = x(1);
    g_x2  = 1 + 9 * sum((x(2:$)-x(1)).^2) / (length(x) - 1);
index d52fb59..7c4c5ea 100644 (file)
             <varlistentry>
                 <term>Log</term>
                 <listitem>
-                    <para>if %T, we will display to information message during the run
-                        of the genetic algorithm.
+                    <para>
+                        if %T, will call the output function at the end of each
+                        iteration, see <literal>"output_func"</literal> under
+                        <varname>param</varname> variable below.
                     </para>
                 </listitem>
             </varlistentry>
                     <itemizedlist>
                         <listitem>
                             <para> 'codage_func': the function which will perform the coding
-                                and decoding of individuals (default function: codage_identity).
+                                and decoding of individuals (default function: <link linkend="coding_ga_identity">coding_ga_identity</link>).
                             </para>
                         </listitem>
                         <listitem>
                             <para> 'init_func': the function which will perform the
                                 initialization of the population (default function:
-                                init_ga_default). 
+                                <link linkend="init_ga_default">init_ga_default</link>).
                             </para>
                         </listitem>
                         <listitem>
                         <listitem>
                             <para> 'crossover_func': the function which will perform the
                                 crossover between two individuals (default function:
-                                crossover_ga_default). 
+                                <link linkend="crossover_ga_default">crossover_ga_default</link>).
                             </para>
                         </listitem>
                         <listitem>
                             <para> 'mutation_func': the function which will perform the
                                 mutation of one individual (default function:
-                                mutation_ga_default). 
+                                <link linkend="mutation_ga_default">mutation_ga_default</link>).
                             </para>
                         </listitem>
                         <listitem>
                             <para> 'selection_func': the function whcih will perform the
                                 selection of individuals at the end of a generation (default
-                                function: selection_ga_elitist). 
+                                function: <link linkend="selection_ga_elitist">selection_ga_elitist</link>).
                             </para>
                         </listitem>
                         <listitem>
                             <para> 'nb_couples': the number of couples which will be
                                 selected so as to perform the crossover and mutation (default
-                                value: 100). 
+                                value: 100).
                             </para>
                         </listitem>
                         <listitem>
                                 individual (default value: 0.05).
                             </para>
                         </listitem>
+                        <listitem>
+                            <para>
+                                "output_func": a callback function called after each
+                                generation if <varname>Log</varname> is %T (default
+                                function <literal>output_nsga_default</literal>).
+                            </para>
+                        </listitem>
                     </itemizedlist>
                 </listitem>
             </varlistentry>
     </refsection>
     <refsection>
         <title>Examples</title>
-        <programlisting role="example"><![CDATA[ 
+        <programlisting role="example"><![CDATA[
 function f = deb_1(x)
    f1_x1 = x(1);
    g_x2  = 1 + 9 * sum((x(2:$)-x(1)).^2) / (length(x) - 1);
index 2f24b02..dda910c 100644 (file)
             <varlistentry>
                 <term>Log</term>
                 <listitem>
-                    <para>if %T, we will display to information message during the run
-                        of the genetic algorithm.
+                    <para>
+                        if %T, will call the output function at the end of each
+                        iteration, see <literal>"output_func"</literal> under
+                        <varname>param</varname> variable below.
                     </para>
                 </listitem>
             </varlistentry>
                     <itemizedlist>
                         <listitem>
                             <para> 'codage_func': the function which will perform the coding
-                                and decoding of individuals (default function: codage_identity).
+                                and decoding of individuals (default function: <link linkend="coding_ga_identity">coding_ga_identity</link>).
                             </para>
                         </listitem>
                         <listitem>
                             <para> 'init_func': the function which will perform the
                                 initialization of the population (default function:
-                                init_ga_default). 
+                                <link linkend="init_ga_default">init_ga_default</link>).
                             </para>
                         </listitem>
                         <listitem>
                         <listitem>
                             <para> 'crossover_func': the function which will perform the
                                 crossover between two individuals (default function:
-                                crossover_ga_default). 
+                                <link linkend="crossover_ga_default">crossover_ga_default</link>).
                             </para>
                         </listitem>
                         <listitem>
                             <para> 'mutation_func': the function which will perform the
                                 mutation of one individual (default function:
-                                mutation_ga_default). 
+                                <link linkend="mutation_ga_default">mutation_ga_default</link>).
                             </para>
                         </listitem>
                         <listitem>
                             <para> 'selection_func': the function whcih will perform the
                                 selection of individuals at the end of a generation (default
-                                function: selection_ga_elitist). 
+                                function: <link linkend="selection_ga_elitist">selection_ga_elitist</link>).
                             </para>
                         </listitem>
                         <listitem>
                             <para> 'nb_couples': the number of couples which will be
                                 selected so as to perform the crossover and mutation (default
-                                value: 100). 
+                                value: 100).
                             </para>
                         </listitem>
                         <listitem>
                                 individual (default value: 0.05).
                             </para>
                         </listitem>
+                        <listitem>
+                            <para>
+                                "output_func": a callback function called after each
+                                generation if <varname>Log</varname> is %T (default
+                                function <literal>output_nsga2_default</literal>).
+                            </para>
+                        </listitem>
                     </itemizedlist>
                 </listitem>
             </varlistentry>
     </refsection>
     <refsection>
         <title>Examples</title>
-        <programlisting role="example"><![CDATA[ 
+        <programlisting role="example"><![CDATA[
 function f = deb_1(x)
    f1_x1 = x(1);
    g_x2  = 1 + 9 * sum((x(2:$)-x(1)).^2) / (length(x) - 1);
diff --git a/scilab/modules/genetic_algorithms/help/en_US/utilities/output_ga_default.xml b/scilab/modules/genetic_algorithms/help/en_US/utilities/output_ga_default.xml
new file mode 100644 (file)
index 0000000..15e5c74
--- /dev/null
@@ -0,0 +1,93 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
+ * Copyright (C) 2014 - Michael BAUDIN <michael.baudin@contrib.scilab.org>
+ * Copyright (C) 2014 - Scilab Enterprises - Pierre-Aime AGNEL
+ *
+ * This file must be used under the terms of the CeCILL.
+ * This source file is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution.  The terms
+ * are also available at
+ * http://www.cecill.info/licences/Licence_CeCILL_V2.1-en.txt
+ *
+ -->
+<refentry xmlns="http://docbook.org/ns/docbook" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:svg="http://www.w3.org/2000/svg" xmlns:ns3="http://www.w3.org/1999/xhtml" xmlns:mml="http://www.w3.org/1998/Math/MathML" xmlns:db="http://docbook.org/ns/docbook" xmlns:scilab="http://www.scilab.org" xml:id="output_ga_default" xml:lang="en">
+    <refnamediv>
+        <refname>output_ga_default</refname>
+        <refpurpose>A simple output function used for logging purposes</refpurpose>
+    </refnamediv>
+    <refsynopsisdiv>
+        <title>Calling Sequence</title>
+        <synopsis>stop = output_ga_default(gen_index, nb_generation, Pop, FObj_Pop, param)</synopsis>
+    </refsynopsisdiv>
+    <refsection>
+        <title>Arguments</title>
+        <variablelist>
+            <varlistentry>
+                <term>gen_index</term>
+                <listitem>
+                    <para>The index of the current generation.</para>
+                </listitem>
+            </varlistentry>
+            <varlistentry>
+                <term>nb_generation</term>
+                <listitem>
+                    <para>The maximum number of generations.</para>
+                </listitem>
+            </varlistentry>
+            <varlistentry>
+                <term>Pop</term>
+                <listitem>
+                    <para>The current population.</para>
+                </listitem>
+            </varlistentry>
+            <varlistentry>
+                <term>FObj_Pop</term>
+                <listitem>
+                    <para>The evaluation for each member of the population.</para>
+                </listitem>
+            </varlistentry>
+            <varlistentry>
+                <term>param</term>
+                <listitem>
+                    <para>A parameter list for optional parameters.</para>
+                </listitem>
+            </varlistentry>
+            <varlistentry>
+                <term>stop</term>
+                <listitem>
+                    <para>A boolean. If %F, will stop the execution of the genetic algorithm.</para>
+                </listitem>
+            </varlistentry>
+        </variablelist>
+    </refsection>
+    <refsection>
+        <title>Description</title>
+        <para>
+            This function displays information on the current step of the genetic algorithm.
+        </para>
+        <para>
+            Use this function to implement a callback after each iteration of the genetic algorithm.
+            This can be used, for instance, to plot intermediate result or log more information on
+            the population.
+        </para>
+        <para>
+            The output parameter <varname>stop</varname> can be used to stop the genetic algorithm
+            altogether if set to %F.
+        </para>
+    </refsection>
+    <refsection role="see also">
+        <title>See Also</title>
+        <simplelist type="inline">
+            <member>
+                <link linkend="optim_moga"> optim_moga </link>
+            </member>
+            <member>
+                <link linkend="optim_nsga"> optim_nsga </link>
+            </member>
+            <member>
+                <link linkend="optim_nsga2"> optim_nsga2 </link>
+            </member>
+        </simplelist>
+    </refsection>
+</refentry>
index 3f4fa1f..7bd0f37 100644 (file)
@@ -12,64 +12,61 @@ function [pop_opt, fobj_pop_opt, pop_init, fobj_pop_init] = optim_ga(ga_f, pop_s
 
     [nargout, nargin] = argn();
 
-    if ~isdef("param","local") then
+    if ~isdef("param", "local") then
         param = [];
     end
 
-    [codage_func,err]    = get_param(param,"codage_func",coding_ga_identity);
-    [init_func,err]      = get_param(param,"init_func",init_ga_default);
-    [crossover_func,err] = get_param(param,"crossover_func",crossover_ga_default);
-    [mutation_func,err]  = get_param(param,"mutation_func",mutation_ga_default);
-    [selection_func,err] = get_param(param,"selection_func",selection_ga_elitist);
-    [nb_couples,err]     = get_param(param,"nb_couples",100);
-    [pressure,err]       = get_param(param,"pressure",0.05);
-
-    if ~isdef("ga_f","local") then
-        error(sprintf(gettext("%s: ga_f is mandatory"),"optim_ga"));
+    [codage_func, err]    = get_param(param, "codage_func", coding_ga_identity);
+    [init_func, err]      = get_param(param, "init_func", init_ga_default);
+    [crossover_func, err] = get_param(param, "crossover_func", crossover_ga_default);
+    [mutation_func, err]  = get_param(param, "mutation_func", mutation_ga_default);
+    [selection_func, err] = get_param(param, "selection_func", selection_ga_elitist);
+    [nb_couples, err]     = get_param(param, "nb_couples", 100);
+    [pressure, err]       = get_param(param, "pressure", 0.05);
+    [output_func, err] = get_param(param, "output_func", output_ga_default);
+
+    if ~isdef("ga_f", "local") then
+        error(sprintf(gettext("%s: ga_f is mandatory"), "optim_ga"));
     else
-        if typeof(ga_f)=="list" then
-            deff("y=_ga_f(x)","y=ga_f(1)(x, ga_f(2:$))");
+        if typeof(ga_f) == "list" then
+            deff("y = _ga_f(x)", "y = ga_f(1)(x, ga_f(2:$))");
         else
-            deff("y=_ga_f(x)","y=ga_f(x)");
+            deff("y = _ga_f(x)", "y = ga_f(x)");
         end
     end
 
-    if ~isdef("pop_size","local") then
+    if ~isdef("pop_size", "local") then
         pop_size = 100;
     end
-    if ~isdef("nb_generation","local") then
+    if ~isdef("nb_generation", "local") then
         nb_generation = 10;
     end
-    if ~isdef("p_mut","local") then
+    if ~isdef("p_mut", "local") then
         p_mut = 0.1;
     end
-    if ~isdef("p_cross","local") then
+    if ~isdef("p_cross", "local") then
         p_cross = 0.7;
     end
-    if ~isdef("Log","local") then
+    if ~isdef("Log", "local") then
         Log = %F;
     end
 
     // Initialization of the population
-    if (Log) then
-        printf(gettext("%s: Initialization of the population\n"),"optim_ga");
-    end
-
     Pop = list();
-    Pop = init_func(pop_size,param);
+    Pop = init_func(pop_size, param);
 
-    if (nargout>=3) then
+    if (nargout >= 3) then
         pop_init = Pop;
     end
 
     // Code the individuals
-    Pop = codage_func(Pop,"code",param);
+    Pop = codage_func(Pop, "code", param);
 
-    for i=1:length(Pop)
+    for i = 1:length(Pop)
         FObj_Pop(i) = _ga_f(Pop(i));
     end
 
-    if (nargout==4) then
+    if (nargout == 4) then
         fobj_pop_init = FObj_Pop;
     end
 
@@ -80,24 +77,21 @@ function [pop_opt, fobj_pop_opt, pop_init, fobj_pop_init] = optim_ga(ga_f, pop_s
     Efficiency = (1 - pressure) * (FObj_Pop_Max - FObj_Pop) / max([FObj_Pop_Max - FObj_Pop_Min %eps]) + pressure;
 
     // The genetic algorithm
-    for i=1:nb_generation
-        if (Log) then
-            printf(gettext("%s: iteration %d / %d"), "optim_ga", i, nb_generation);
-        end
+    for i = 1:nb_generation
         //
         // Selection
         //
         Indiv1 = list();
         Indiv2 = list();
         Wheel = cumsum(Efficiency);
-        for j=1:nb_couples
+        for j = 1:nb_couples
             // Selection of the first individual in the couple
-            Shoot = grand(1,1,"unf", 0, Wheel($));
+            Shoot = grand(1, 1, "unf", 0, Wheel($));
             Index = find(Shoot <= Wheel, 1);
             Indiv1(j)      = Pop(Index);
             FObj_Indiv1(j) = FObj_Pop(Index);
             // Selection of the second individual in the couple
-            Shoot = grand(1,1,"unf", 0, Wheel($));
+            Shoot = grand(1, 1, "unf", 0, Wheel($));
             Index = 1;
             Index = find(Shoot <= Wheel, 1);
             Indiv2(j)      = Pop(Index);
@@ -106,8 +100,8 @@ function [pop_opt, fobj_pop_opt, pop_init, fobj_pop_init] = optim_ga(ga_f, pop_s
         //
         // Crossover
         //
-        for j=1:nb_couples
-            if (p_cross>grand(1,1,"def")) then
+        for j = 1:nb_couples
+            if (p_cross>grand(1, 1, "def")) then
                 [x1, x2] = crossover_func(Indiv1(j), Indiv2(j), param);
                 Indiv1(j) = x1;
                 Indiv2(j) = x2;
@@ -121,14 +115,14 @@ function [pop_opt, fobj_pop_opt, pop_init, fobj_pop_init] = optim_ga(ga_f, pop_s
         //
         // Mutation
         //
-        for j=1:nb_couples
-            if (p_mut>grand(1,1,"def")) then
-                x1 = mutation_func(Indiv1(j),param);
+        for j = 1:nb_couples
+            if (p_mut>grand(1, 1, "def")) then
+                x1 = mutation_func(Indiv1(j), param);
                 Indiv1(j) = x1;
                 ToCompute_I1(j) = %T;
             end
-            if (p_mut>grand(1,1,"def")) then
-                x2 = mutation_func(Indiv2(j),param);
+            if (p_mut>grand(1, 1, "def")) then
+                x2 = mutation_func(Indiv2(j), param);
                 Indiv2(j) = x2;
                 ToCompute_I2(j) = %T;
             end
@@ -136,7 +130,7 @@ function [pop_opt, fobj_pop_opt, pop_init, fobj_pop_init] = optim_ga(ga_f, pop_s
         //
         // Computation of the objective functions
         //
-        for j=1:nb_couples
+        for j = 1:nb_couples
             if ToCompute_I1(j) then FObj_Indiv1(j) = _ga_f(Indiv1(j)); end
             if ToCompute_I2(j) then FObj_Indiv2(j) = _ga_f(Indiv2(j)); end
         end
@@ -148,15 +142,18 @@ function [pop_opt, fobj_pop_opt, pop_init, fobj_pop_init] = optim_ga(ga_f, pop_s
         //
         // Recombination
         //
+        [Pop, FObj_Pop] = selection_func(Pop, Indiv1, Indiv2, FObj_Pop, FObj_Indiv1, FObj_Indiv2, [], [], [], param);
 
-        [Pop, FObj_Pop, Efficiency] = selection_func(Pop,Indiv1,Indiv2,FObj_Pop,FObj_Indiv1,FObj_Indiv2,[],[],[],param);
-
+        // Callback for plotting / printing intermediate results or stopping the algorithm
         if (Log) then
-            printf(gettext(" - min / max value found = %f / %f\n"), min(FObj_Pop), max(FObj_Pop));
+            stop = output_func(i, nb_generation, Pop, FObj_Pop, param);
+            if (stop) then
+                break
+            end
         end
     end
 
     pop_opt  = Pop;
-    pop_opt  = codage_func(pop_opt,"decode",param);
+    pop_opt  = codage_func(pop_opt, "decode", param);
     fobj_pop_opt = FObj_Pop;
 endfunction
index fd0a36b..13ff5db 100644 (file)
@@ -23,6 +23,7 @@ function [pop_opt, fobj_pop_opt, pop_init, fobj_pop_init] = optim_moga(ga_f, pop
     [selection_func,err] = get_param(param,"selection_func",selection_ga_elitist);
     [nb_couples,err]     = get_param(param,"nb_couples",100);
     [pressure,err]       = get_param(param,"pressure",0.05);
+    [output_func, err] = get_param(param, "output_func", output_moga_default);
 
     if ~isdef("ga_f","local") then
         error(gettext("optim_moga: ga_f is mandatory"));
@@ -56,7 +57,7 @@ function [pop_opt, fobj_pop_opt, pop_init, fobj_pop_init] = optim_moga(ga_f, pop
     end
 
     Pop = list();
-    Pop = init_func(pop_size,param);
+    Pop = init_func(pop_size, param);
 
     if (nargout>=3) then
         pop_init = Pop;
@@ -91,9 +92,6 @@ function [pop_opt, fobj_pop_opt, pop_init, fobj_pop_init] = optim_moga(ga_f, pop
 
     // The genetic algorithm
     for i=1:nb_generation
-        if (Log) then
-            printf(gettext("%s: iteration %d / %d"), "optim_moga", i, nb_generation);
-        end
         //
         // Selection
         //
@@ -196,13 +194,16 @@ function [pop_opt, fobj_pop_opt, pop_init, fobj_pop_init] = optim_moga(ga_f, pop
         // Recombination
         //
 
-        [Pop,FObj_Pop,Efficiency,MO_FObj_Pop] = selection_func(Pop,Indiv1,Indiv2,FObj_Pop,FObj_Indiv1,FObj_Indiv2, ...
-        MO_FObj_Pop,MO_FObj_Indiv1,MO_FObj_Indiv2,param);
+        [Pop, FObj_Pop, Efficiency, MO_FObj_Pop] = selection_func(Pop, Indiv1, Indiv2, FObj_Pop, FObj_Indiv1, FObj_Indiv2, ...
+                MO_FObj_Pop, MO_FObj_Indiv1, MO_FObj_Indiv2, param);
         if (Log) then
-            printf(gettext(" - min / max value found = %f / %f\n"), min(FObj_Pop), max(FObj_Pop));
+            stop = output_func(i, nb_generation, Pop, MO_FObj_Pop, param);
+            if stop then
+                break
+            end
         end
     end
 
-    pop_opt      = codage_func(Pop,"decode",param);
+    pop_opt      = codage_func(Pop, 'decode', param);
     fobj_pop_opt = MO_FObj_Pop;
 endfunction
index e739a38..419d13f 100644 (file)
@@ -11,57 +11,58 @@ function [pop_opt, fobj_pop_opt, pop_init, fobj_pop_init] = optim_nsga(ga_f, pop
 
     [nargout, nargin] = argn();
 
-    if ~isdef("param","local") then
+    if ~isdef("param", "local") then
         param = [];
     end
 
-    [codage_func,err]    = get_param(param,"codage_func",coding_ga_identity);
-    [init_func,err]      = get_param(param,"init_func",init_ga_default);
-    [crossover_func,err] = get_param(param,"crossover_func",crossover_ga_default);
-    [mutation_func,err]  = get_param(param,"mutation_func",mutation_ga_default);
-    [selection_func,err] = get_param(param,"selection_func",selection_ga_elitist);
-    [nb_couples,err]     = get_param(param,"nb_couples",100);
-    [pressure,err]       = get_param(param,"pressure",0.05);
+    [codage_func, err]    = get_param(param, "codage_func", coding_ga_identity);
+    [init_func, err]      = get_param(param, "init_func", init_ga_default);
+    [crossover_func, err] = get_param(param, "crossover_func", crossover_ga_default);
+    [mutation_func, err]  = get_param(param, "mutation_func", mutation_ga_default);
+    [selection_func, err] = get_param(param, "selection_func", selection_ga_elitist);
+    [nb_couples, err]     = get_param(param, "nb_couples", 100);
+    [pressure, err]       = get_param(param, "pressure", 0.05);
+    [output_func, err] = get_param(param, "output_func", output_nsga_default);
 
-    if ~isdef("ga_f","local") then
+    if ~isdef("ga_f", "local") then
         error(gettext("optim_moga: ga_f is mandatory"));
     else
         if typeof(ga_f)=="list" then
-            deff("y=_ga_f(x)","y=ga_f(1)(x, ga_f(2:$))");
+            deff("y=_ga_f(x)", "y=ga_f(1)(x, ga_f(2:$))");
         else
-            deff("y=_ga_f(x)","y=ga_f(x)");
+            deff("y=_ga_f(x)", "y=ga_f(x)");
         end
     end
 
-    if ~isdef("pop_size","local") then
+    if ~isdef("pop_size", "local") then
         pop_size = 100;
     end
-    if ~isdef("nb_generation","local") then
+    if ~isdef("nb_generation", "local") then
         nb_generation = 10;
     end
-    if ~isdef("p_mut","local") then
+    if ~isdef("p_mut", "local") then
         p_mut = 0.1;
     end
-    if ~isdef("p_cross","local") then
+    if ~isdef("p_cross", "local") then
         p_cross = 0.1;
     end
-    if ~isdef("Log","local") then
+    if ~isdef("Log", "local") then
         Log = %F;
     end
-    if ~isdef("sigma","local") then
+    if ~isdef("sigma", "local") then
         sigma = 0.01;
     end
-    if ~isdef("pow","local") then
+    if ~isdef("pow", "local") then
         pow = 2;
     end
 
     // Initialization of the population
     if (Log) then
-        printf(gettext("%s: Initialization of the population\n"),"optim_nsga");
+        printf(gettext("%s: Initialization of the population\n"), "optim_nsga");
     end
 
     Pop = list();
-    Pop = init_func(pop_size,param);
+    Pop = init_func(pop_size, param);
 
 
     if (nargout>=3) then
@@ -69,17 +70,17 @@ function [pop_opt, fobj_pop_opt, pop_init, fobj_pop_init] = optim_nsga(ga_f, pop
     end
 
     // Code the individuals
-    Pop = codage_func(Pop,"code",param);
+    Pop = codage_func(Pop, "code", param);
 
     for i=1:length(Pop)
-        MO_FObj_Pop(i,:) = _ga_f(Pop(i));
+        MO_FObj_Pop(i, :) = _ga_f(Pop(i));
     end
 
     // Compute the domination rank
-    for i=1:size(MO_FObj_Pop,1)
+    for i=1:size(MO_FObj_Pop, 1)
         Index = 0;
-        for j=1:size(MO_FObj_Pop,1)
-            Index = Index + double(and(MO_FObj_Pop(i,:)<=MO_FObj_Pop(j,:)) & or(MO_FObj_Pop(i,:)<MO_FObj_Pop(j,:)));
+        for j=1:size(MO_FObj_Pop, 1)
+            Index = Index + double(and(MO_FObj_Pop(i, :)<=MO_FObj_Pop(j, :)) & or(MO_FObj_Pop(i, :)<MO_FObj_Pop(j, :)));
         end
         FObj_Pop(i) = - (Index + 1);
     end
@@ -90,15 +91,11 @@ function [pop_opt, fobj_pop_opt, pop_init, fobj_pop_init] = optim_nsga(ga_f, pop
 
     // The genetic algorithm
     for i=1:nb_generation
-        if (Log) then
-            printf(gettext("%s: iteration %d / %d"), "optim_nsga", i, nb_generation);
-        end
-
         // Computation of the niching penality
-        for j=1:size(MO_FObj_Pop,1)
+        for j=1:size(MO_FObj_Pop, 1)
             Niching(j) = 0;
-            for k=1:size(MO_FObj_Pop,1)
-                Distance = sqrt(sum((MO_FObj_Pop(j,:) - MO_FObj_Pop(k,:)).^2));
+            for k=1:size(MO_FObj_Pop, 1)
+                Distance = sqrt(sum((MO_FObj_Pop(j, :) - MO_FObj_Pop(k, :)).^2));
                 if Distance < sigma then
                     Niching(j) = Niching(j) + (1 - Distance / sigma)^pow;
                 end
@@ -123,26 +120,26 @@ function [pop_opt, fobj_pop_opt, pop_init, fobj_pop_init] = optim_nsga(ga_f, pop
 
         for j=1:nb_couples
             // Selection of the first individual in the couple
-            Shoot = grand(1,1,"def")*Wheel($);
+            Shoot = grand(1, 1, "def")*Wheel($);
             Index = find(Wheel<=Shoot);
             if length(Index)>1 then Index = Index($); end;
             if isempty(Index)  then Index = 1; end;
             Indiv1(j)           = Pop(Index);
-            MO_FObj_Indiv1(j,:) = MO_FObj_Pop(Index,:);
+            MO_FObj_Indiv1(j, :) = MO_FObj_Pop(Index, :);
             // Selection of the second individual in the couple
-            Shoot = grand(1,1,"def")*Wheel($);
+            Shoot = grand(1, 1, "def")*Wheel($);
             Index = find(Wheel<=Shoot);
             if length(Index)>1 then Index = Index($); end;
             if isempty(Index)  then Index = 1; end;
             Indiv2(j)           = Pop(Index);
-            MO_FObj_Indiv2(j,:) = MO_FObj_Pop(Index,:);
+            MO_FObj_Indiv2(j, :) = MO_FObj_Pop(Index, :);
         end
         //
         // Crossover
         //
         for j=1:nb_couples
-            if (p_cross>grand(1,1,"def")) then
-                [x1, x2]  = crossover_func(Indiv1(j), Indiv2(j),param);
+            if (p_cross>grand(1, 1, "def")) then
+                [x1, x2]  = crossover_func(Indiv1(j), Indiv2(j), param);
                 Indiv1(j) = x1;
                 Indiv2(j) = x2;
                 ToCompute_I1(j) = %T;
@@ -156,13 +153,13 @@ function [pop_opt, fobj_pop_opt, pop_init, fobj_pop_init] = optim_nsga(ga_f, pop
         // Mutation
         //
         for j=1:nb_couples
-            if (p_mut>grand(1,1,"def")) then
-                x1 = mutation_func(Indiv1(j),param);
+            if (p_mut>grand(1, 1, "def")) then
+                x1 = mutation_func(Indiv1(j), param);
                 Indiv1(j) = x1;
                 ToCompute_I1(j) = %T;
             end
-            if (p_mut>grand(1,1,"def")) then
-                x2 = mutation_func(Indiv2(j),param);
+            if (p_mut>grand(1, 1, "def")) then
+                x2 = mutation_func(Indiv2(j), param);
                 Indiv2(j) = x2;
                 ToCompute_I2(j) = %T;
             end
@@ -171,8 +168,8 @@ function [pop_opt, fobj_pop_opt, pop_init, fobj_pop_init] = optim_nsga(ga_f, pop
         // Computation of the objective functions
         //
         for j=1:length(Indiv1)
-            if ToCompute_I1(j) then MO_FObj_Indiv1(j,:) = _ga_f(Indiv1(j)); end
-            if ToCompute_I2(j) then MO_FObj_Indiv2(j,:) = _ga_f(Indiv2(j)); end
+            if ToCompute_I1(j) then MO_FObj_Indiv1(j, :) = _ga_f(Indiv1(j)); end
+            if ToCompute_I2(j) then MO_FObj_Indiv2(j, :) = _ga_f(Indiv2(j)); end
         end
 
         // Reinit ToCompute lists
@@ -180,39 +177,39 @@ function [pop_opt, fobj_pop_opt, pop_init, fobj_pop_init] = optim_nsga(ga_f, pop
         ToCompute_I2 = ToCompute_I2 & %F;
 
         // Compute the domination rank
-        for j=1:size(MO_FObj_Indiv1,1)
+        for j=1:size(MO_FObj_Indiv1, 1)
             // We compute the rank for Indiv1
             Index1 = 0; Index2 = 0; Index3 = 0;
-            for k=1:size(MO_FObj_Indiv1,1)
-                Index1 = Index1 + double(and(MO_FObj_Indiv1(j,:)<=MO_FObj_Indiv1(k,:)) & or(MO_FObj_Indiv1(j,:)<MO_FObj_Indiv1(k,:)));
-                Index2 = Index2 + double(and(MO_FObj_Indiv1(j,:)<=MO_FObj_Indiv2(k,:)) & or(MO_FObj_Indiv1(j,:)<MO_FObj_Indiv2(k,:)));
+            for k=1:size(MO_FObj_Indiv1, 1)
+                Index1 = Index1 + double(and(MO_FObj_Indiv1(j, :)<=MO_FObj_Indiv1(k, :)) & or(MO_FObj_Indiv1(j, :)<MO_FObj_Indiv1(k, :)));
+                Index2 = Index2 + double(and(MO_FObj_Indiv1(j, :)<=MO_FObj_Indiv2(k, :)) & or(MO_FObj_Indiv1(j, :)<MO_FObj_Indiv2(k, :)));
             end
-            for k=1:size(MO_FObj_Pop,1)
-                Index3 = Index3 + and(MO_FObj_Indiv1(j,:)<=MO_FObj_Pop(k,:)) & or(MO_FObj_Indiv1(j,:)<MO_FObj_Pop(k,:));
+            for k=1:size(MO_FObj_Pop, 1)
+                Index3 = Index3 + and(MO_FObj_Indiv1(j, :)<=MO_FObj_Pop(k, :)) & or(MO_FObj_Indiv1(j, :)<MO_FObj_Pop(k, :));
             end
             FObj_Indiv1(j) = - (Index1 + Index2 + Index3 + 1);
 
             // We compute the rank for Indiv2
             Index1 = 0; Index2 = 0; Index3 = 0;
-            for k=1:size(MO_FObj_Indiv1,1)
-                Index1 = Index1 + double(and(MO_FObj_Indiv2(j,:)<=MO_FObj_Indiv1(k,:)) & or(MO_FObj_Indiv2(j,:)<MO_FObj_Indiv1(k,:)));
-                Index2 = Index2 + double(and(MO_FObj_Indiv2(j,:)<=MO_FObj_Indiv2(k,:)) & or(MO_FObj_Indiv2(j,:)<MO_FObj_Indiv2(k,:)));
+            for k=1:size(MO_FObj_Indiv1, 1)
+                Index1 = Index1 + double(and(MO_FObj_Indiv2(j, :)<=MO_FObj_Indiv1(k, :)) & or(MO_FObj_Indiv2(j, :)<MO_FObj_Indiv1(k, :)));
+                Index2 = Index2 + double(and(MO_FObj_Indiv2(j, :)<=MO_FObj_Indiv2(k, :)) & or(MO_FObj_Indiv2(j, :)<MO_FObj_Indiv2(k, :)));
             end
-            for k=1:size(MO_FObj_Pop,1)
-                Index3 = Index3 + double(and(MO_FObj_Indiv2(j,:)<=MO_FObj_Pop(k,:)) & or(MO_FObj_Indiv2(j,:)<MO_FObj_Pop(k,:)));
+            for k=1:size(MO_FObj_Pop, 1)
+                Index3 = Index3 + double(and(MO_FObj_Indiv2(j, :)<=MO_FObj_Pop(k, :)) & or(MO_FObj_Indiv2(j, :)<MO_FObj_Pop(k, :)));
             end
             FObj_Indiv2(j) = - (Index1 + Index2 + Index3 + 1);
         end
 
         // We compute the rank for Pop
-        for j=1:size(MO_FObj_Pop,1)
+        for j=1:size(MO_FObj_Pop, 1)
             Index1 = 0; Index2 = 0; Index3 = 0;
-            for k=1:size(MO_FObj_Indiv1,1)
-                Index1 = Index1 + double(and(MO_FObj_Pop(j,:)<=MO_FObj_Indiv1(k,:)) & or(MO_FObj_Pop(j,:)<MO_FObj_Indiv1(k,:)));
-                Index2 = Index2 + double(and(MO_FObj_Pop(j,:)<=MO_FObj_Indiv2(k,:)) & or(MO_FObj_Pop(j,:)<MO_FObj_Indiv2(k,:)));
+            for k=1:size(MO_FObj_Indiv1, 1)
+                Index1 = Index1 + double(and(MO_FObj_Pop(j, :)<=MO_FObj_Indiv1(k, :)) & or(MO_FObj_Pop(j, :)<MO_FObj_Indiv1(k, :)));
+                Index2 = Index2 + double(and(MO_FObj_Pop(j, :)<=MO_FObj_Indiv2(k, :)) & or(MO_FObj_Pop(j, :)<MO_FObj_Indiv2(k, :)));
             end
-            for k=1:size(FObj_Pop,1)
-                Index3 = Index3 + double(and(MO_FObj_Pop(j,:)<=MO_FObj_Pop(k,:)) & or(MO_FObj_Pop(j,:)<MO_FObj_Pop(k,:)));
+            for k=1:size(FObj_Pop, 1)
+                Index3 = Index3 + double(and(MO_FObj_Pop(j, :)<=MO_FObj_Pop(k, :)) & or(MO_FObj_Pop(j, :)<MO_FObj_Pop(k, :)));
             end
             FObj_Pop(j) = - (Index1 + Index2 + Index3 + 1);
         end
@@ -221,13 +218,16 @@ function [pop_opt, fobj_pop_opt, pop_init, fobj_pop_init] = optim_nsga(ga_f, pop
         // Recombination
         //
 
-        [Pop,FObj_Pop,Efficiency,MO_FObj_Pop] = selection_func(Pop,Indiv1,Indiv2,FObj_Pop,FObj_Indiv1,FObj_Indiv2, ...
-        MO_FObj_Pop,MO_FObj_Indiv1,MO_FObj_Indiv2,param);
+        [Pop, FObj_Pop, Efficiency, MO_FObj_Pop] = selection_func(Pop, Indiv1, Indiv2, FObj_Pop, FObj_Indiv1, FObj_Indiv2, ...
+        MO_FObj_Pop, MO_FObj_Indiv1, MO_FObj_Indiv2, param);
         if (Log) then
-            printf(gettext(" - min / max value found = %f / %f\n"), min(FObj_Pop), max(FObj_Pop));
+            stop = output_func(i, nb_generation, Pop, FObj_Pop, param);
+            if stop then
+                break
+            end
         end
     end
 
-    pop_opt      = codage_func(Pop,"decode",param);
+    pop_opt      = codage_func(Pop, "decode", param);
     fobj_pop_opt = MO_FObj_Pop;
 endfunction
index a449118..a6099c2 100644 (file)
@@ -11,58 +11,59 @@ function [pop_opt, fobj_pop_opt, pop_init, fobj_pop_init] = optim_nsga2(ga_f, po
 
     [nargout, nargin] = argn();
 
-    if ~isdef("param","local") then
+    if ~isdef("param", "local") then
         param = [];
     end
 
-    [codage_func,err]        = get_param(param,"codage_func",coding_ga_identity);
-    [init_func,err]          = get_param(param,"init_func",init_ga_default);
-    [crossover_func,err]     = get_param(param,"crossover_func",crossover_ga_default);
-    [mutation_func,err]      = get_param(param,"mutation_func",mutation_ga_default);
-    [nb_couples,err]         = get_param(param,"nb_couples",100);
+    [codage_func, err] = get_param(param, "codage_func", coding_ga_identity);
+    [init_func, err] = get_param(param, "init_func", init_ga_default);
+    [crossover_func, err] = get_param(param, "crossover_func", crossover_ga_default);
+    [mutation_func, err] = get_param(param, "mutation_func", mutation_ga_default);
+    [nb_couples, err] = get_param(param, "nb_couples", 100);
+    [output_func, err] = get_param(param, 'output_func', output_nsga2_default);
 
-    if ~isdef("ga_f","local") then
+    if ~isdef("ga_f", "local") then
         error(gettext("optim_nsga2: ga_f is mandatory"));
     else
         if typeof(ga_f)=="list" then
-            deff("y=_ga_f(x)","y=ga_f(1)(x, ga_f(2:$))");
+            deff("y=_ga_f(x)", "y=ga_f(1)(x, ga_f(2:$))");
         else
-            deff("y=_ga_f(x)","y=ga_f(x)");
+            deff("y=_ga_f(x)", "y=ga_f(x)");
         end
     end
 
-    if ~isdef("pop_size","local") then
+    if ~isdef("pop_size", "local") then
         pop_size = 100;
     end
-    if ~isdef("nb_generation","local") then
+    if ~isdef("nb_generation", "local") then
         nb_generation = 10;
     end
-    if ~isdef("p_mut","local") then
+    if ~isdef("p_mut", "local") then
         p_mut = 0.1;
     end
-    if ~isdef("p_cross","local") then
+    if ~isdef("p_cross", "local") then
         p_cross = 0.1;
     end
-    if ~isdef("Log","local") then
+    if ~isdef("Log", "local") then
         Log = %F;
     end
 
     // Initialization of the population
     if (Log) then
-        printf(gettext("%s: Initialization of the population\n"),"optim_nsga2");
+        printf(gettext("%s: Initialization of the population\n"), "optim_nsga2");
     end
 
-    Pop = init_func(pop_size,param);
+    Pop = init_func(pop_size, param);
 
     if (nargout>=3) then
         pop_init = Pop;
     end
 
     // Code the individuals
-    Pop = codage_func(Pop,"code",param);
+    Pop = codage_func(Pop, "code", param);
 
     for i=1:length(Pop)
-        FObj_Pop(i,:) = _ga_f(Pop(i));
+        FObj_Pop(i, :) = _ga_f(Pop(i));
     end
 
     // Compute the domination rank
@@ -70,18 +71,18 @@ function [pop_opt, fobj_pop_opt, pop_init, fobj_pop_init] = optim_nsga2(ga_f, po
 
     // Compute the crowding distance
     MO_FObj_Pop = FObj_Pop;
-    Index    = 1:size(MO_FObj_Pop,1);
-    Crowdist = zeros(size(MO_FObj_Pop,1),1);
-    for i=1:size(FObj_Pop,2)
-        [tmp, Index_List] = gsort(MO_FObj_Pop(:,i));
-        MO_FObj_Pop       = MO_FObj_Pop(Index_List,:);
+    Index    = 1:size(MO_FObj_Pop, 1);
+    Crowdist = zeros(size(MO_FObj_Pop, 1), 1);
+    for i=1:size(FObj_Pop, 2)
+        [tmp, Index_List] = gsort(MO_FObj_Pop(:, i));
+        MO_FObj_Pop       = MO_FObj_Pop(Index_List, :);
         Index             = Index(Index_List);
         Crowdist(Index_List(1)) = %inf;
         Crowdist(Index_List($)) = %inf;
-        _Max = max(MO_FObj_Pop(:,i));
-        _Min = min(MO_FObj_Pop(:,i));
-        for j=2:size(MO_FObj_Pop,1)-1
-            Crowdist(Index(j)) = Crowdist(Index(j)) - (MO_FObj_Pop(j+1,i) - MO_FObj_Pop(j-1,i)) / (_Max - _Min);
+        _Max = max(MO_FObj_Pop(:, i));
+        _Min = min(MO_FObj_Pop(:, i));
+        for j=2:size(MO_FObj_Pop, 1)-1
+            Crowdist(Index(j)) = Crowdist(Index(j)) - (MO_FObj_Pop(j+1, i) - MO_FObj_Pop(j-1, i)) / (_Max - _Min);
         end
     end
 
@@ -91,9 +92,6 @@ function [pop_opt, fobj_pop_opt, pop_init, fobj_pop_init] = optim_nsga2(ga_f, po
 
     // The genetic algorithm
     for It=1:nb_generation
-        if (Log) then
-            printf(gettext("%s: iteration %d / %d\n"), "optim_nsga2", It, nb_generation);
-        end
         //
         // Selection
         //
@@ -101,32 +99,32 @@ function [pop_opt, fobj_pop_opt, pop_init, fobj_pop_init] = optim_nsga2(ga_f, po
         Indiv2 = list();
         for j=1:nb_couples
             // Selection of 2 individuals via binary tournament selection to fill Indiv1
-            Index1 = ceil((size(FObj_Pop,1) - 1)*grand(1,1,"def")+1);
-            Index2 = ceil((size(FObj_Pop,1) - 1)*grand(1,1,"def")+1);
+            Index1 = ceil((size(FObj_Pop, 1) - 1)*grand(1, 1, "def")+1);
+            Index2 = ceil((size(FObj_Pop, 1) - 1)*grand(1, 1, "def")+1);
             if (Rank(Index1)<Rank(Index2)) | ((Rank(Index1)==Rank(Index2)) & (Crowdist(Index1)>Crowdist(Index2))) then
                 Indiv1(j)        = Pop(Index1);
-                FObj_Indiv1(j,:) = MO_FObj_Pop(Index1,:);
+                FObj_Indiv1(j, :) = MO_FObj_Pop(Index1, :);
             else
                 Indiv1(j)        = Pop(Index2);
-                FObj_Indiv1(j,:) = MO_FObj_Pop(Index2,:);
+                FObj_Indiv1(j, :) = MO_FObj_Pop(Index2, :);
             end
             // Selection of 2 individuals via binary tournament selection to fill Indiv2
-            Index1 = ceil((size(FObj_Pop,1) - 1)*grand(1,1,"def")+1);
-            Index2 = ceil((size(FObj_Pop,1) - 1)*grand(1,1,"def")+1);
+            Index1 = ceil((size(FObj_Pop, 1) - 1)*grand(1, 1, "def")+1);
+            Index2 = ceil((size(FObj_Pop, 1) - 1)*grand(1, 1, "def")+1);
             if (Rank(Index1)<Rank(Index2)) | ((Rank(Index1)==Rank(Index2)) & (Crowdist(Index1)>Crowdist(Index2))) then
                 Indiv2(j)        = Pop(Index1);
-                FObj_Indiv2(j,:) = MO_FObj_Pop(Index1,:);
+                FObj_Indiv2(j, :) = MO_FObj_Pop(Index1, :);
             else
                 Indiv2(j)        = Pop(Index2);
-                FObj_Indiv2(j,:) = MO_FObj_Pop(Index2,:);
+                FObj_Indiv2(j, :) = MO_FObj_Pop(Index2, :);
             end
         end
         //
         // Crossover
         //
         for j=1:nb_couples
-            if (p_cross>grand(1,1,"def")) then
-                [x1, x2] = crossover_func(Indiv1(j), Indiv2(j),param);
+            if (p_cross>grand(1, 1, "def")) then
+                [x1, x2] = crossover_func(Indiv1(j), Indiv2(j), param);
                 Indiv1(j) = x1;
                 Indiv2(j) = x2;
                 ToCompute_I1(j) = %T;
@@ -140,13 +138,13 @@ function [pop_opt, fobj_pop_opt, pop_init, fobj_pop_init] = optim_nsga2(ga_f, po
         // Mutation
         //
         for j=1:nb_couples
-            if (p_mut>grand(1,1,"def")) then
-                x1 = mutation_func(Indiv1(j),param);
+            if (p_mut>grand(1, 1, "def")) then
+                x1 = mutation_func(Indiv1(j), param);
                 Indiv1(j) = x1;
                 ToCompute_I1(j) = %T;
             end
-            if (p_mut>grand(1,1,"def")) then
-                x2 = mutation_func(Indiv2(j),param);
+            if (p_mut>grand(1, 1, "def")) then
+                x2 = mutation_func(Indiv2(j), param);
                 Indiv2(j) = x2;
                 ToCompute_I2(j) = %T;
             end
@@ -155,8 +153,8 @@ function [pop_opt, fobj_pop_opt, pop_init, fobj_pop_init] = optim_nsga2(ga_f, po
         // Computation of the objective functions
         //
         for j=1:length(Indiv1)
-            if ToCompute_I1(j) then FObj_Indiv1(j,:) = _ga_f(Indiv1(j)); end
-            if ToCompute_I2(j) then FObj_Indiv2(j,:) = _ga_f(Indiv2(j)); end
+            if ToCompute_I1(j) then FObj_Indiv1(j, :) = _ga_f(Indiv1(j)); end
+            if ToCompute_I2(j) then FObj_Indiv2(j, :) = _ga_f(Indiv2(j)); end
         end
 
         // Reinit ToCompute lists
@@ -172,26 +170,26 @@ function [pop_opt, fobj_pop_opt, pop_init, fobj_pop_init] = optim_nsga2(ga_f, po
 
         // Compute the crowding distance
         MO_All_FObj = All_FObj;
-        Index    = 1:size(MO_All_FObj,1);
-        Crowdist = zeros(size(MO_All_FObj,1),1);
-        for k=1:size(MO_All_FObj,2)
-            [tmp, Index_List] = gsort(MO_All_FObj(:,k));
-            MO_All_FObj = MO_All_FObj(Index_List,:);
+        Index    = 1:size(MO_All_FObj, 1);
+        Crowdist = zeros(size(MO_All_FObj, 1), 1);
+        for k=1:size(MO_All_FObj, 2)
+            [tmp, Index_List] = gsort(MO_All_FObj(:, k));
+            MO_All_FObj = MO_All_FObj(Index_List, :);
             Index = Index(Index_List);
             Crowdist(Index_List(1)) = %inf;
             Crowdist(Index_List($)) = %inf;
-            _Max = max(MO_All_FObj(:,k));
-            _Min = min(MO_All_FObj(:,k));
-            for j=2:size(MO_All_FObj,1)-1
-                Crowdist(Index(j)) = Crowdist(Index(j)) - (MO_All_FObj(j+1,k) - MO_All_FObj(j-1,k)) / (_Max - _Min);
+            _Max = max(MO_All_FObj(:, k));
+            _Min = min(MO_All_FObj(:, k));
+            for j=2:size(MO_All_FObj, 1)-1
+                Crowdist(Index(j)) = Crowdist(Index(j)) - (MO_All_FObj(j+1, k) - MO_All_FObj(j-1, k)) / (_Max - _Min);
             end
         end
         //
         // Recombination
         //
         // We rank all the individual wrt to the partial order
-        for k=1:size(All_FObj,1)-1
-            for j=k+1:size(All_FObj,1)
+        for k=1:size(All_FObj, 1)-1
+            for j=k+1:size(All_FObj, 1)
                 if (Rank(j)<Rank(k)) | ((Rank(j)==Rank(k)) & (Crowdist(j)>Crowdist(k))) then
                     tmp           = Rank(k);
                     Rank(k)       = Rank(j);
@@ -202,21 +200,28 @@ function [pop_opt, fobj_pop_opt, pop_init, fobj_pop_init] = optim_nsga2(ga_f, po
                     tmp           = All_Pop(k);
                     All_Pop(k)    = All_Pop(j);
                     All_Pop(j)    = tmp;
-                    tmp           = All_FObj(k,:);
-                    All_FObj(k,:) = All_FObj(j,:);
-                    All_FObj(j,:) = tmp;
+                    tmp           = All_FObj(k, :);
+                    All_FObj(k, :) = All_FObj(j, :);
+                    All_FObj(j, :) = tmp;
                 end
             end
         end
         // Extraction and selection of the phenotype
-        FObj_Pop = All_FObj(1:pop_size,:);
+        FObj_Pop = All_FObj(1:pop_size, :);
         // Extraction and selection of the genotype
         Pop = list(All_Pop(1:pop_size));
         // Extraction of the ranks and Crow distance
         Rank     = Rank(1:pop_size);
         Crowdist = Crowdist(1:pop_size);
+
+        if (Log) then
+            stop = output_func(i, nb_generation, Pop, FObj_Pop, param);
+            if stop then
+                break
+            end
+        end
     end
 
-    pop_opt      = codage_func(Pop,"decode",param);
+    pop_opt      = codage_func(Pop, "decode", param);
     fobj_pop_opt = FObj_Pop;
 endfunction
diff --git a/scilab/modules/genetic_algorithms/macros/output_ga_default.sci b/scilab/modules/genetic_algorithms/macros/output_ga_default.sci
new file mode 100644 (file)
index 0000000..66c92e3
--- /dev/null
@@ -0,0 +1,16 @@
+// =============================================================================
+// Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
+// Copyright (C) 2014 - Michael BAUDIN <michael.baudin@contrib.scilab.org>
+//
+// This file must be used under the terms of the CeCILL.
+// This source file is licensed as described in the file COPYING, which
+// you should have received as part of this distribution.  The terms
+// are also available at
+// http://www.cecill.info/licences/Licence_CeCILL_V2.1-en.txt
+// =============================================================================
+
+function stop = output_ga_default(gen_index, nb_generation, Pop, FObj_Pop, param)
+    printf(gettext("%s: iteration %d / %d \n"), "optim_ga", gen_index, nb_generation);
+    printf(gettext("    min / max value found = %f / %f\n"), min(FObj_Pop), max(FObj_Pop));
+    stop = %f
+endfunction
diff --git a/scilab/modules/genetic_algorithms/macros/output_moga_default.sci b/scilab/modules/genetic_algorithms/macros/output_moga_default.sci
new file mode 100644 (file)
index 0000000..607f2c0
--- /dev/null
@@ -0,0 +1,16 @@
+// =============================================================================
+// Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
+// Copyright (C) Scilab Enterprises - 2014 - Pierre-Aime Agnel
+//
+// This file must be used under the terms of the CeCILL.
+// This source file is licensed as described in the file COPYING, which
+// you should have received as part of this distribution.  The terms
+// are also available at
+// http://www.cecill.info/licences/Licence_CeCILL_V2.1-en.txt
+// =============================================================================
+
+function stop = output_moga_default(gen_index, nb_generation, Pop, FObj_Pop, param)
+    printf(gettext("%s: iteration %d / %d \n"), "optim_moga", gen_index, nb_generation);
+    printf(gettext("    min / max value found = %f / %f\n"), min(FObj_Pop), max(FObj_Pop));
+    stop = %f
+endfunction
diff --git a/scilab/modules/genetic_algorithms/macros/output_nsga2_default.sci b/scilab/modules/genetic_algorithms/macros/output_nsga2_default.sci
new file mode 100644 (file)
index 0000000..e38472e
--- /dev/null
@@ -0,0 +1,16 @@
+// =============================================================================
+// Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
+// Copyright (C) Scilab Enterprises - 2014 - Pierre-Aime Agnel
+//
+// This file must be used under the terms of the CeCILL.
+// This source file is licensed as described in the file COPYING, which
+// you should have received as part of this distribution.  The terms
+// are also available at
+// http://www.cecill.info/licences/Licence_CeCILL_V2.1-en.txt
+// =============================================================================
+
+function stop = output_nsga2_default(gen_index, nb_generation, Pop, FObj_Pop, param)
+    printf(gettext("%s: iteration %d / %d\n"), "optim_nsga2", It, nb_generation);
+    printf(gettext("    min / max value found = %f / %f\n"), min(FObj_Pop), max(FObj_Pop));
+    stop = %f
+endfunction
diff --git a/scilab/modules/genetic_algorithms/macros/output_nsga_default.sci b/scilab/modules/genetic_algorithms/macros/output_nsga_default.sci
new file mode 100644 (file)
index 0000000..3fc89a6
--- /dev/null
@@ -0,0 +1,17 @@
+// =============================================================================
+// Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
+// Copyright (C) Scilab Enterprises - 2014 - Pierre-Aime Agnel
+//
+// This file must be used under the terms of the CeCILL.
+// This source file is licensed as described in the file COPYING, which
+// you should have received as part of this distribution.  The terms
+// are also available at
+// http://www.cecill.info/licences/Licence_CeCILL_V2.1-en.txt
+// =============================================================================
+
+function stop = output_nsga_default(gen_index, nb_generation, Pop, FObj_Pop, param)
+    printf(gettext("%s: iteration %d / %d \n"), "optim_nsga", gen_index, nb_generation);
+    printf(gettext("    min / max value found = %f / %f\n"), min(FObj_Pop), max(FObj_Pop));
+    stop = %f
+endfunction
+
diff --git a/scilab/modules/genetic_algorithms/tests/nonreg_tests/bug_13421.dia.ref b/scilab/modules/genetic_algorithms/tests/nonreg_tests/bug_13421.dia.ref
new file mode 100644 (file)
index 0000000..9ba2701
--- /dev/null
@@ -0,0 +1,86 @@
+// =============================================================================
+// Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
+// Copyright (C) 2014 - Scilab Enterprises - Pierre-Aime Agnel
+//
+//  This file is distributed under the same license as the Scilab package.
+// =============================================================================
+//
+// <-- Non-regression test for bug  -->
+//
+// <-- Bugzilla URL -->
+// http://bugzilla.scilab.org/13421
+//
+// <-- Short Description -->
+// Callback functions for genetic algorithms were missing
+//
+// <-- CLI SHELL MODE -->
+// Objective function
+function y=f(x)
+  y = sum(x.^2)
+endfunction
+// Output function with a stop criterion
+function stop=output_ga_custom(gen_index, nb_generation, Pop, FObj_Pop, param)
+    [threshold, err] = get_param(param, "threshold", 1E-10); // default value for the threshold
+    printf(_("%s: iteration %d / %d \n"), "optim_ga", gen_index, nb_generation);
+    printf(_("    min / max value found = %.4E / %.4E\n"), min(FObj_Pop), max(FObj_Pop));
+    stop = %f
+    if abs(max(FObj_Pop) - min(FObj_Pop)) < threshold then
+        printf(_("    Stop criterion reached: Delta Max to Min under threshold"));
+        stop = %t
+    end
+endfunction
+PopSize     = 100;
+Proba_cross = 0.7;
+Proba_mut   = 0.1;
+NbGen       = 20;
+NbCouples   = 110;
+Log         = %T;
+pressure    = 0.05;
+ga_params = init_param();
+// Parameters to adapt to the shape of the optimization problem
+ga_params = add_param(ga_params,"minbound",[-2; -2]);
+ga_params = add_param(ga_params,"maxbound",[2; 2]);
+ga_params = add_param(ga_params,"dimension",2);
+ga_params = add_param(ga_params,"beta",0);
+ga_params = add_param(ga_params,"delta",0.1);
+// Parameters to fine tune the Genetic algorithm.
+// All these parameters are optional for continuous optimization
+// If you need to adapt the GA to a special problem, you
+ga_params = add_param(ga_params,"init_func",init_ga_default);
+ga_params = add_param(ga_params,"crossover_func",crossover_ga_default);
+ga_params = add_param(ga_params,"mutation_func",mutation_ga_default);
+ga_params = add_param(ga_params,"codage_func",coding_ga_identity);
+ga_params = add_param(ga_params,"selection_func",selection_ga_elitist);
+//ga_params = add_param(ga_params,"selection_func",selection_ga_random);
+ga_params = add_param(ga_params,"nb_couples",NbCouples);
+ga_params = add_param(ga_params,"pressure",pressure);
+// Customized output function with a stop criterion added
+ga_params = add_param(ga_params, "threshold", 1E-6); // User defined parameter for the output function
+ga_params = add_param(ga_params, "output_func", output_ga_custom);
+[pop_opt, fobj_pop_opt, pop_init, fobj_pop_init] = ..
+  optim_ga(f, PopSize, NbGen, Proba_mut, Proba_cross, Log, ga_params);
+optim_ga: iteration 1 / 20 
+    min / max value found = 6.4854E-03 / 1.1026E+00
+optim_ga: iteration 2 / 20 
+    min / max value found = 4.2909E-03 / 2.8682E-01
+optim_ga: iteration 3 / 20 
+    min / max value found = 3.1174E-05 / 5.6912E-02
+optim_ga: iteration 4 / 20 
+    min / max value found = 3.1174E-05 / 1.8523E-02
+optim_ga: iteration 5 / 20 
+    min / max value found = 3.1174E-05 / 4.2909E-03
+optim_ga: iteration 6 / 20 
+    min / max value found = 2.0292E-05 / 1.2683E-03
+optim_ga: iteration 7 / 20 
+    min / max value found = 9.9116E-06 / 2.9666E-04
+optim_ga: iteration 8 / 20 
+    min / max value found = 1.1124E-06 / 7.9347E-05
+optim_ga: iteration 9 / 20 
+    min / max value found = 4.0632E-07 / 3.3694E-05
+optim_ga: iteration 10 / 20 
+    min / max value found = 3.4754E-07 / 9.9116E-06
+optim_ga: iteration 11 / 20 
+    min / max value found = 3.4470E-08 / 2.2709E-06
+optim_ga: iteration 12 / 20 
+    min / max value found = 3.4470E-08 / 9.0795E-07
+    Stop criterion reached: Delta Max to Min under thresholdassert_checktrue(max(fobj_pop_opt) - min(fobj_pop_opt) <= 1E-6);
diff --git a/scilab/modules/genetic_algorithms/tests/nonreg_tests/bug_13421.tst b/scilab/modules/genetic_algorithms/tests/nonreg_tests/bug_13421.tst
new file mode 100644 (file)
index 0000000..a9e2f17
--- /dev/null
@@ -0,0 +1,70 @@
+// =============================================================================
+// Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
+// Copyright (C) 2014 - Scilab Enterprises - Pierre-Aime Agnel
+//
+//  This file is distributed under the same license as the Scilab package.
+// =============================================================================
+//
+// <-- Non-regression test for bug  -->
+//
+// <-- Bugzilla URL -->
+// http://bugzilla.scilab.org/13421
+//
+// <-- Short Description -->
+// Callback functions for genetic algorithms were missing
+//
+// <-- CLI SHELL MODE -->
+
+// Objective function
+function y=f(x)
+  y = sum(x.^2)
+endfunction
+
+// Output function with a stop criterion
+function stop=output_ga_custom(gen_index, nb_generation, Pop, FObj_Pop, param)
+    [threshold, err] = get_param(param, "threshold", 1E-10); // default value for the threshold
+    printf(_("%s: iteration %d / %d \n"), "optim_ga", gen_index, nb_generation);
+    printf(_("    min / max value found = %.4E / %.4E\n"), min(FObj_Pop), max(FObj_Pop));
+    stop = %f
+    if abs(max(FObj_Pop) - min(FObj_Pop)) < threshold then
+        printf(_("    Stop criterion reached: Delta Max to Min under threshold"));
+        stop = %t
+    end
+endfunction
+
+PopSize     = 100;
+Proba_cross = 0.7;
+Proba_mut   = 0.1;
+NbGen       = 20;
+NbCouples   = 110;
+Log         = %T;
+pressure    = 0.05;
+
+ga_params = init_param();
+// Parameters to adapt to the shape of the optimization problem
+ga_params = add_param(ga_params,"minbound",[-2; -2]);
+ga_params = add_param(ga_params,"maxbound",[2; 2]);
+ga_params = add_param(ga_params,"dimension",2);
+ga_params = add_param(ga_params,"beta",0);
+ga_params = add_param(ga_params,"delta",0.1);
+// Parameters to fine tune the Genetic algorithm.
+// All these parameters are optional for continuous optimization
+// If you need to adapt the GA to a special problem, you
+ga_params = add_param(ga_params,"init_func",init_ga_default);
+ga_params = add_param(ga_params,"crossover_func",crossover_ga_default);
+ga_params = add_param(ga_params,"mutation_func",mutation_ga_default);
+ga_params = add_param(ga_params,"codage_func",coding_ga_identity);
+ga_params = add_param(ga_params,"selection_func",selection_ga_elitist);
+
+//ga_params = add_param(ga_params,"selection_func",selection_ga_random);
+ga_params = add_param(ga_params,"nb_couples",NbCouples);
+ga_params = add_param(ga_params,"pressure",pressure);
+
+// Customized output function with a stop criterion added
+ga_params = add_param(ga_params, "threshold", 1E-6); // User defined parameter for the output function
+ga_params = add_param(ga_params, "output_func", output_ga_custom);
+
+[pop_opt, fobj_pop_opt, pop_init, fobj_pop_init] = ..
+  optim_ga(f, PopSize, NbGen, Proba_mut, Proba_cross, Log, ga_params);
+
+assert_checktrue(max(fobj_pop_opt) - min(fobj_pop_opt) <= 1E-6);
index 6a7b2c0..d43025b 100644 (file)
@@ -39,27 +39,39 @@ ga_params = add_param(ga_params, "maxbound", ones(2, 1));
 [pop_opt, fobj_pop_opt, pop_init, fobj_pop_init] = ..
 optim_moga(list(deb_2, 1, 9), PopSize, NbGen, Proba_mut, Proba_cross, Log, ga_params);
 optim_moga: Initialization of the population
-optim_moga: iteration 1 / 4 - min / max value found = -117.000000 / -59.000000
-optim_moga: iteration 2 / 4 - min / max value found = -62.000000 / -32.000000
-optim_moga: iteration 3 / 4 - min / max value found = -54.000000 / -15.000000
-optim_moga: iteration 4 / 4 - min / max value found = -59.000000 / -22.000000
+optim_moga: iteration 1 / 4 
+    min / max value found = 0.029324 / 1.259517
+optim_moga: iteration 2 / 4 
+    min / max value found = 0.098841 / 0.732534
+optim_moga: iteration 3 / 4 
+    min / max value found = 0.124679 / 0.656770
+optim_moga: iteration 4 / 4 
+    min / max value found = 0.225319 / 0.525795
 assert_checkequal(length(pop_opt), length(pop_init));
 assert_checkequal(size(fobj_pop_opt), size(fobj_pop_init));
 [pop_opt, fobj_pop_opt, pop_init, fobj_pop_init] = ..
 optim_nsga(list(deb_2, 1, 9), PopSize, NbGen, Proba_mut, Proba_cross, Log, ga_params);
 optim_nsga: Initialization of the population
-optim_nsga: iteration 1 / 4 - min / max value found = -138.000000 / -57.000000
-optim_nsga: iteration 2 / 4 - min / max value found = -69.000000 / -30.000000
-optim_nsga: iteration 3 / 4 - min / max value found = -33.000000 / -16.000000
-optim_nsga: iteration 4 / 4 - min / max value found = -26.000000 / -10.000000
+optim_nsga: iteration 1 / 4 
+    min / max value found = -138.000000 / -57.000000
+optim_nsga: iteration 2 / 4 
+    min / max value found = -69.000000 / -30.000000
+optim_nsga: iteration 3 / 4 
+    min / max value found = -33.000000 / -16.000000
+optim_nsga: iteration 4 / 4 
+    min / max value found = -26.000000 / -10.000000
 assert_checkequal(length(pop_opt), length(pop_init));
 assert_checkequal(size(fobj_pop_opt), size(fobj_pop_init));
 [pop_opt, fobj_pop_opt, pop_init, fobj_pop_init] = ..
 optim_nsga2(list(deb_2, 1, 9), PopSize, NbGen, Proba_mut, Proba_cross, Log, ga_params);
 optim_nsga2: Initialization of the population
 optim_nsga2: iteration 1 / 4
+    min / max value found = 0.002139 / 7.982432
 optim_nsga2: iteration 2 / 4
+    min / max value found = 0.000000 / 1.777920
 optim_nsga2: iteration 3 / 4
+    min / max value found = 0.000000 / 4.417277
 optim_nsga2: iteration 4 / 4
+    min / max value found = 0.000000 / 1.323218
 assert_checkequal(length(pop_opt), length(pop_init));
 assert_checkequal(size(fobj_pop_opt), size(fobj_pop_init));
index 240792d..fbff95a 100644 (file)
@@ -49,17 +49,26 @@ ga_params = add_param(ga_params, "nb_couples", NbCouples);
 ga_params = add_param(ga_params, "pressure", pressure);
 [pop_opt, fobj_pop_opt, pop_init, fobj_pop_init] = ..
 optim_ga(f, PopSize, NbGen, Proba_mut, Proba_cross, Log, ga_params);
-optim_ga: Initialization of the population
-optim_ga: iteration 1 / 10 - min / max value found = 0.001391 / 0.995046
-optim_ga: iteration 2 / 10 - min / max value found = 0.000206 / 0.191417
-optim_ga: iteration 3 / 10 - min / max value found = 0.000126 / 0.048784
-optim_ga: iteration 4 / 10 - min / max value found = 0.000118 / 0.011398
-optim_ga: iteration 5 / 10 - min / max value found = 0.000046 / 0.001167
-optim_ga: iteration 6 / 10 - min / max value found = 0.000034 / 0.000284
-optim_ga: iteration 7 / 10 - min / max value found = 0.000004 / 0.000114
-optim_ga: iteration 8 / 10 - min / max value found = 0.000001 / 0.000036
-optim_ga: iteration 9 / 10 - min / max value found = 0.000000 / 0.000010
-optim_ga: iteration 10 / 10 - min / max value found = 0.000000 / 0.000003
+optim_ga: iteration 1 / 10 
+    min / max value found = 0.001391 / 0.995046
+optim_ga: iteration 2 / 10 
+    min / max value found = 0.000341 / 0.177816
+optim_ga: iteration 3 / 10 
+    min / max value found = 0.000133 / 0.044825
+optim_ga: iteration 4 / 10 
+    min / max value found = 0.000002 / 0.010889
+optim_ga: iteration 5 / 10 
+    min / max value found = 0.000002 / 0.001507
+optim_ga: iteration 6 / 10 
+    min / max value found = 0.000002 / 0.000310
+optim_ga: iteration 7 / 10 
+    min / max value found = 0.000001 / 0.000089
+optim_ga: iteration 8 / 10 
+    min / max value found = 0.000000 / 0.000014
+optim_ga: iteration 9 / 10 
+    min / max value found = 0.000000 / 0.000003
+optim_ga: iteration 10 / 10 
+    min / max value found = 0.000000 / 0.000001
 assert_checkequal(length(pop_opt), length(pop_init));
 assert_checkequal(size(fobj_pop_opt), size(fobj_pop_init));
 // Customizing the init function, which computes the initial population.
@@ -90,19 +99,28 @@ ga_params = add_param(ga_params, "dimension", 2);
 ga_params = add_param(ga_params, "init_func", myinitga);
 [pop_opt, fobj_pop_opt, pop_init, fobj_pop_init] = ..
 optim_ga(f, PopSize, NbGen, Proba_mut, Proba_cross, Log, ga_params);
-optim_ga: Initialization of the population
  
  Initializing the Population with grand   
-optim_ga: iteration 1 / 10 - min / max value found = 0.010016 / 0.928237
-optim_ga: iteration 2 / 10 - min / max value found = 0.006862 / 0.161421
-optim_ga: iteration 3 / 10 - min / max value found = 0.001781 / 0.037628
-optim_ga: iteration 4 / 10 - min / max value found = 0.000544 / 0.011567
-optim_ga: iteration 5 / 10 - min / max value found = 0.000039 / 0.003271
-optim_ga: iteration 6 / 10 - min / max value found = 0.000039 / 0.001117
-optim_ga: iteration 7 / 10 - min / max value found = 0.000005 / 0.000307
-optim_ga: iteration 8 / 10 - min / max value found = 0.000001 / 0.000092
-optim_ga: iteration 9 / 10 - min / max value found = 0.000000 / 0.000034
-optim_ga: iteration 10 / 10 - min / max value found = 0.000000 / 0.000010
+optim_ga: iteration 1 / 10 
+    min / max value found = 0.010016 / 0.928237
+optim_ga: iteration 2 / 10 
+    min / max value found = 0.001402 / 0.198423
+optim_ga: iteration 3 / 10 
+    min / max value found = 0.000809 / 0.045008
+optim_ga: iteration 4 / 10 
+    min / max value found = 0.000053 / 0.013969
+optim_ga: iteration 5 / 10 
+    min / max value found = 0.000053 / 0.003974
+optim_ga: iteration 6 / 10 
+    min / max value found = 0.000040 / 0.000922
+optim_ga: iteration 7 / 10 
+    min / max value found = 0.000005 / 0.000240
+optim_ga: iteration 8 / 10 
+    min / max value found = 0.000001 / 0.000057
+optim_ga: iteration 9 / 10 
+    min / max value found = 0.000000 / 0.000020
+optim_ga: iteration 10 / 10 
+    min / max value found = 0.000000 / 0.000007
 assert_checkequal(length(pop_opt), length(pop_init));
 assert_checkequal(size(fobj_pop_opt), size(fobj_pop_init));
 // Passing a list to the optim_ga function, where the first element of the list is
@@ -121,16 +139,25 @@ a2 = 7;
 myobjfun = list(f, a1, a2);
 // Optimize !
 [pop_opt, fobj_pop_opt] = optim_ga(myobjfun, PopSize, NbGen, Proba_mut, Proba_cross, Log, ga_params);
-optim_ga: Initialization of the population
-optim_ga: iteration 1 / 10 - min / max value found = 7.339791 / 29.150584
-optim_ga: iteration 2 / 10 - min / max value found = 7.199192 / 11.923950
-optim_ga: iteration 3 / 10 - min / max value found = 7.199192 / 8.613638
-optim_ga: iteration 4 / 10 - min / max value found = 7.106121 / 7.425043
-optim_ga: iteration 5 / 10 - min / max value found = 7.026332 / 7.199192
-optim_ga: iteration 6 / 10 - min / max value found = 7.002293 / 7.078284
-optim_ga: iteration 7 / 10 - min / max value found = 7.002293 / 7.032606
-optim_ga: iteration 8 / 10 - min / max value found = 7.000564 / 7.012589
-optim_ga: iteration 9 / 10 - min / max value found = 7.000280 / 7.004547
-optim_ga: iteration 10 / 10 - min / max value found = 7.000039 / 7.001819
+optim_ga: iteration 1 / 10 
+    min / max value found = 7.339791 / 29.150584
+optim_ga: iteration 2 / 10 
+    min / max value found = 7.054037 / 12.127766
+optim_ga: iteration 3 / 10 
+    min / max value found = 7.048084 / 9.120917
+optim_ga: iteration 4 / 10 
+    min / max value found = 7.025101 / 7.630176
+optim_ga: iteration 5 / 10 
+    min / max value found = 7.007453 / 7.191936
+optim_ga: iteration 6 / 10 
+    min / max value found = 7.005699 / 7.054037
+optim_ga: iteration 7 / 10 
+    min / max value found = 7.000896 / 7.020325
+optim_ga: iteration 8 / 10 
+    min / max value found = 7.000375 / 7.007070
+optim_ga: iteration 9 / 10 
+    min / max value found = 7.000156 / 7.002255
+optim_ga: iteration 10 / 10 
+    min / max value found = 7.000112 / 7.000828
 assert_checkequal(length(pop_opt), length(pop_init));
 assert_checkequal(size(fobj_pop_opt), size(fobj_pop_init));