{
  "cells": [
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "collapsed": false
      },
      "outputs": [],
      "source": [
        "%matplotlib inline"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\n# Self-Organizing Map\n\nIn this example, we illustrate the use of the :class:`~gemseo.post.som.SOM` plot\non the Sobieski's SSBJ problem.\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "collapsed": false
      },
      "outputs": [],
      "source": [
        "from __future__ import annotations\n\nfrom gemseo.api import configure_logger\nfrom gemseo.api import create_discipline\nfrom gemseo.api import create_scenario\nfrom gemseo.problems.sobieski.core.problem import SobieskiProblem\nfrom matplotlib import pyplot as plt"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "## Import\nThe first step is to import some functions from the API\nand a method to get the design space.\n\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "collapsed": false
      },
      "outputs": [],
      "source": [
        "configure_logger()"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "## Description\n\nThe :class:`~gemseo.post.som.SOM` post-processing performs a Self Organizing Map\nclustering on the optimization history.\nA :class:`~gemseo.post.som.SOM` is a 2D representation of a design of experiments\nwhich requires dimensionality reduction since it may be in a very high dimension.\n\nA :term:`SOM` is built by using an unsupervised artificial neural network\n:cite:`Kohonen:2001`.\nA map of size ``n_x.n_y`` is generated, where\n``n_x`` is the number of neurons in the $x$ direction and ``n_y``\nis the number of neurons in the $y$ direction. The design space\n(whatever the dimension) is reduced to a 2D representation based on\n``n_x.n_y`` neurons. Samples are clustered to a neuron when their design\nvariables are close in terms of their L2 norm. A neuron is always located at the\nsame place on a map. Each neuron is colored according to the average value for\na given criterion. This helps to qualitatively analyze whether parts of the design\nspace are good according to some criteria and not for others, and where\ncompromises should be made. A white neuron has no sample associated with\nit: not enough evaluations were provided to train the SOM.\n\nSOM's provide a qualitative view of the :term:`objective function`, the\n:term:`constraints`, and of their relative behaviors.\n\n"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "## Create disciplines\nAt this point, we instantiate the disciplines of Sobieski's SSBJ problem:\nPropulsion, Aerodynamics, Structure and Mission\n\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "collapsed": false
      },
      "outputs": [],
      "source": [
        "disciplines = create_discipline(\n    [\n        \"SobieskiPropulsion\",\n        \"SobieskiAerodynamics\",\n        \"SobieskiStructure\",\n        \"SobieskiMission\",\n    ]\n)"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "## Create design space\nWe also read the design space from the :class:`.SobieskiProblem`.\n\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "collapsed": false
      },
      "outputs": [],
      "source": [
        "design_space = SobieskiProblem().design_space"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "## Create and execute scenario\nThe next step is to build an MDO scenario in order to maximize the range,\nencoded 'y_4', with respect to the design parameters, while satisfying the\ninequality constraints 'g_1', 'g_2' and 'g_3'. We can use the MDF formulation,\nthe Monte Carlo DOE algorithm and 30 samples.\n\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "collapsed": false
      },
      "outputs": [],
      "source": [
        "scenario = create_scenario(\n    disciplines,\n    formulation=\"MDF\",\n    objective_name=\"y_4\",\n    maximize_objective=True,\n    design_space=design_space,\n    scenario_type=\"DOE\",\n)\nscenario.set_differentiation_method(\"user\")\nfor constraint in [\"g_1\", \"g_2\", \"g_3\"]:\n    scenario.add_constraint(constraint, \"ineq\")\nscenario.execute({\"algo\": \"OT_MONTE_CARLO\", \"n_samples\": 30})"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "## Post-process scenario\nLastly, we post-process the scenario by means of the\n:class:`~gemseo.post.som.SOM` plot which performs a self organizing map\nclustering on optimization history.\n\n"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        ".. tip::\n\n   Each post-processing method requires different inputs and offers a variety\n   of customization options. Use the API function\n   :meth:`~gemseo.api.get_post_processing_options_schema` to print a table with\n   the options for any post-processing algorithm.\n   Or refer to our dedicated page:\n   `gen_post_algos`.\n\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "collapsed": false
      },
      "outputs": [],
      "source": [
        "scenario.post_process(\"SOM\", save=False, show=False)\n# Workaround for HTML rendering, instead of ``show=True``\nplt.show()"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "Figure `fig-ssbj-mdf-som100` illustrates another :term:`SOM` on the Sobieski\nuse case. The optimization method is a (costly) derivative free algorithm\n(``NLOPT_COBYLA``), indeed all the relevant information for the optimization\nis obtained at the cost of numerous evaluations of the functions. For\nmore details, please read the paper by\n:cite:`kumano2006multidisciplinary` on wing MDO post-processing\nusing SOM.\n\n\n.. figure:: /tutorials/ssbj/figs/MDOScenario_SOM_v100.png\n    :scale: 10 %\n\n    SOM example on the Sobieski problem.\n\nA DOE may also be a good way to produce SOM maps.\nFigure `fig-ssbj-mdf-som10000` shows an example with 10000 points on\nthe same test case. This produces more relevant SOM plots.\n\n\n.. figure:: /tutorials/ssbj/figs/som_fine.png\n    :scale: 55 %\n\n    SOM example on the Sobieski problem with a 10 000 samples DOE.\n\n"
      ]
    }
  ],
  "metadata": {
    "kernelspec": {
      "display_name": "Python 3",
      "language": "python",
      "name": "python3"
    },
    "language_info": {
      "codemirror_mode": {
        "name": "ipython",
        "version": 3
      },
      "file_extension": ".py",
      "mimetype": "text/x-python",
      "name": "python",
      "nbconvert_exporter": "python",
      "pygments_lexer": "ipython3",
      "version": "3.9.13"
    }
  },
  "nbformat": 4,
  "nbformat_minor": 0
}