<?xml version="1.0" encoding="UTF-8"?>
<!--
 * Scilab ( https://www.scilab.org/ ) - This file is part of Scilab
 * Copyright (C) INRIA -
 * Copyright (C) 2012 - 2016 - Scilab Enterprises
 * Copyright (C) 2020 - Samuel GOUGEON
 *
 * This file is hereby licensed under the terms of the GNU GPL v2.0,
 * pursuant to article 5.3.4 of the CeCILL v.2.1.
 * This file was originally licensed under the terms of the CeCILL v2.1,
 * and continues to be available under such terms.
 * For more information, see the COPYING file which you should have received
 * along with this program.
 *
 -->
<refentry xmlns="http://docbook.org/ns/docbook" xmlns:xlink="http://www.w3.org/1999/xlink"
          xmlns:svg="http://www.w3.org/2000/svg" xmlns:mml="http://www.w3.org/1998/Math/MathML"
          xmlns:db="http://docbook.org/ns/docbook" xmlns:scilab="http://www.scilab.org"
          xml:lang="en" xml:id="riccati">
    <refnamediv>
        <refname>riccati</refname>
        <refpurpose>Solves the matricial Riccati equation (continuous | discrete time domain)</refpurpose>
    </refnamediv>
    <refsynopsisdiv>
        <title>Syntax</title>
        <synopsis>
            X = riccati(H)
            X = riccati(H, E)
            X = riccati(A, B, C, dom)
            X = riccati(A, B, C, dom, method)
            [X1, X2, residual] = riccati(...)
        </synopsis>
    </refsynopsisdiv>
    <refsection>
       <title>Arguments</title>
        <variablelist>
            <varlistentry>
                <term>A, B, C</term>
                <listitem>
                    Square matrices of real numbers, of size n x n: Matricial coefficients
                    of the equation.
                    <para/>
                </listitem>
            </varlistentry>
            <varlistentry>
                <term>H, E</term>
                <listitem>
                    Square matrices of real numbers, of size 2n x 2n: Hamiltonian matrices | pencil
                    of the equation.
                    <para/>
                </listitem>
            </varlistentry>
            <varlistentry>
                <term>dom</term>
                <listitem>
                    Type / time domain of the Riccati equation:
                    <literal>"c"</literal> or <literal>"continuous"</literal>, or
                    <literal>"d"</literal> or <literal>"discrete"</literal>.
                    <para/>
                </listitem>
            </varlistentry>
            <varlistentry>
                <term>method</term>
                <listitem>
                    string : <literal>"eigen"</literal> for block diagonalization (default), or
                    <literal>"schur"</literal> for  Schur method.
                    <para/>
                </listitem>
            </varlistentry>
            <varlistentry>
                <term>X1, X2, X</term>
                <listitem>
                    square matrices of real numbers (X2 invertible). X is symetric when B and C
                    are so.
                    <para/>
                </listitem>
            </varlistentry>
            <varlistentry>
                <term>residual</term>
                <listitem>
                    real number: norm<subscript>1</subscript> of the actual Equation(X) residue.
                    <para/>
                </listitem>
            </varlistentry>
        </variablelist>
        <para/>
    </refsection>

    <refsection>
        <title>Description</title>
        <refsect3>
            <title>Continuous time domain</title>
            <para>
                <emphasis role="bold">X = riccati(A, B, C, "c")</emphasis> solves the matricial
                Riccati equation:
            </para>
            <para>
                <literal>A'*X + X*A - X*B*X + C = 0</literal>
            </para>
           <para>
                <emphasis role="bold">X = riccati(H)</emphasis>
                where <literal>H = [A, -B ; -C, -A']</literal> is the Hamiltonian matrix,
                does the same, using the 'eigen' method, but is more stable.
            </para>
        </refsect3>
        <refsect3>
            <title>Discrete time domain</title>
            <para>
                <emphasis role="bold">X = riccati(A, B, C, "d")</emphasis> solves the Riccati equation:
            </para>
            <para>
                <literal>A'*X*A - (A'*X*B<subscript>1</subscript>) / (B<subscript>2</subscript> +
                B<subscript>1</subscript>'*X*B<subscript>1</subscript>) *
                (B<subscript>1</subscript>'*X*A) + C - X = 0</literal>
            </para>
            <para>
                with <literal>B = B<subscript>1</subscript> / B<subscript>2</subscript> *
                B<subscript>1</subscript>'</literal>.
            </para>
            <para>
                <emphasis role="bold">X = riccati(H, E)</emphasis> does the same, where
                <literal>H = [A, zeros(n,n) ; -C, eye(n,n)]</literal> and
                <literal>E = [eye(n,n), B ; zeros(n,n), A']</literal>
                define the Hamiltonian pencil <literal>(E,H)</literal>.
            </para>
        </refsect3>
        <refsect3>
            <title>Output options</title>
            <para>
                <emphasis role="bold">[X1, X2] = riccati(..)</emphasis> provides
                <literal>X1</literal> and <literal>X2</literal>, with <literal>X2</literal> invertible,
                such that <literal>X = X1 / X2</literal>.
            </para>
            <para>
                <literal>residual</literal> is the L1-norm of the actual equation's result. If
                <literal>X</literal> is an actual solution, <literal>residual</literal> should be 0.
                Most often its value is close to <literal>%eps*norm(X)</literal>.
            </para>
            <warning>
                In the <literal>discrete</literal> case, sometimes
                <literal>B<subscript>1</subscript></literal> and
                <literal>B<subscript>2</subscript></literal> can't be retrieved from <literal>B</literal>.
                Then <literal>residual</literal> can't be assessed and is set to <literal>%nan</literal>.
            </warning>
        </refsect3>
        <warning>
            When no solution is found, <literal>X=[]</literal> or <literal>X1=[]</literal> is
            returned, and a warning is yielded.
        </warning>
    </refsection>

    <refsection>
        <title>Examples</title>
        <emphasis role="bold">Continuous time domain</emphasis>
        <para>
        <programlisting role="example"><![CDATA[
n = 3;
// [A, B, C] = (grand(n,n,"uin",-9,9), grand(n,n,"uin",-9,9), grand(n,n,"uin",-9,9))
A = [
  -62.   91.   57.
  -43.  -45.  -19.
   58.   83.  -62.
   ];
B = [
   75.  -31.  -10.
  -79.   70.   68.
  -72.  -5.    32.
   ];
C = [
  -56.   70.   58.
  -41.   54.   50.
   90.   2.   -40.
   ];

// With A, B, C
// ------------
X = riccati(A, B, C, "c")
clean(A'*X + X*A - X*B*X + C)
[x1, x2, res] = riccati(A,B,C, "c");
x = x1 / x2;
and(x==X)
res

// With the Hamiltonian
// --------------------
H = [A, -B; -C, -A'];
X = riccati(H)
clean(A'*X + X*A - X*B*X + C)
[x1, x2] = riccati(H);
x = x1 / x2;
and(x==X)
    ]]></programlisting>
        <screen>
--> X = riccati(A, B, C, "c")
 X  =
  -0.1790367   0.4166084   0.2319152
  -0.4977093   0.7993495   0.3086213
   0.5595286   0.3202094  -0.103394

--> clean(A'*X + X*A - X*B*X + C)
 ans  =
   0.   0.   0.
   0.   0.   0.
   0.   0.   0.

--> [x1, x2, res] = riccati(A,B,C, "c");
--> x = x1 / x2;
--> and(x==X)
 ans  =
  T

--> res
 res  =
   3.340D-13


--> // With the Hamiltonian
--> // --------------------
--> H = [A, -B; -C, -A'];
--> X = riccati(H);
 X  =
  -0.1790367   0.4166084   0.2319152
  -0.4977093   0.7993495   0.3086213
   0.5595286   0.3202094  -0.103394

--> clean(A'*X + X*A - X*B*X + C)
 ans  =
   0.   0.   0.
   0.   0.   0.
   0.   0.   0.

--> [x1, x2] = riccati(H);
--> x = x1 / x2;
--> and(x==X)
 ans  =
  T
</screen>
        </para>

        <emphasis role="bold">Discrete time domain</emphasis>
        <para/>
        <programlisting role="example"><![CDATA[
// Eq: A'*X*A - (A'*X*B1) / (B2 + B1'*X*B1) * (B1'*X*A) + C - X = 0
n = 4;
[A, B1, B2, C] = (rand(n,n), rand(n,n), rand(n,n), rand(n,n));
B  = B1 / B2 * B1';

X = riccati(A, B, C, 'd', 'schur')
if X <> [] then
    clean(A'*X*A - (A'*X*B1) / (B2 + B1'*X*B1) * (B1'*X*A) + C - X)
    [x1, x2, res] = riccati(A, B, C, 'd', 'schur');
    x = x1 / x2;
    and(x==X)
    res
else
    disp("Riccati: No solution found")
end
     ]]></programlisting>
    </refsection>

    <refsection role="see also">
        <title>See also</title>
        <simplelist type="inline">
            <member>
                <link linkend="ricc">ricc</link>
            </member>
            <member>
                <link linkend="srfaur">srfaur</link>
            </member>
            <member>
                <link linkend="lindquist">lindquist</link>
            </member>
        </simplelist>
    </refsection>

    <refsection role="history">
        <title>History</title>
        <revhistory>
            <revision>
                <revnumber>6.1.0</revnumber>
                <revdescription>
                    <itemizedlist>
                        <listitem>
                            <literal>riccati(H)</literal> and <literal>riccati(H,E)</literal> added.
                        </listitem>
                        <listitem>
                            <literal>residual</literal> output added.
                        </listitem>
                        <listitem>
                            When no solution is found, <literal>X=[]</literal> |
                            <literal>X1=[]</literal> is now returned, without error.
                        </listitem>
                    </itemizedlist>
                </revdescription>
            </revision>
        </revhistory>
    </refsection>
</refentry>
