import apprentissage.DescenteGradient;
import apprentissage.IFonction;
import java.awt.*;
import java.awt.event.*;
import java.io.IOException;
import java.io.Writer;
import java.util.*;
import javax.swing.*;
 
public class Bracketing extends JApplet implements ActionListener, MouseListener, IFonction
{
 
    public Bracketing()
    {
        pane = new JPanel(new BorderLayout());
        boutons = new JPanel();
        bNouvelleFonction = new JButton("Nouvelle Fonction");
        bBalayage = new JButton("Balayage");
        bDichotomie = new JButton("Dichotomie");
        points = new LinkedList();
        coeffs = new double[10];
        v = 0.5D;
    } // Bracketing()
 
    /***************************
    * The function to discover *
    ***************************/
     
    protected double fonction(double d)
    {
        double d1 = coeffs[0];
        for(int i = 1; i < 5; i++)
            d1 += coeffs[i] * Math.sin(d * (double)(1 + i) * 3.14159D);
 
        d1 += 5D * coeffs[5] * Math.pow(d, 2D);
        d1 += 5D * coeffs[6] * Math.pow(d, 3D);
        d1 += 5D * coeffs[7] * Math.pow(d, 4D);
        d1 += 5D * coeffs[8] * Math.pow(d, 5D);
        d1 += 5D * coeffs[9] * Math.pow(d, 6D);
        return d1;
    } // fonction(double)
 
    /*****************
    * Event Managing *
    *****************/
    
    protected void nouvelleFonction()
    {
        for(int i = 0; i < coeffs.length; i++)
            coeffs[i] = Math.random() - Math.random();
 
        double d = fonction(0.0D);
        double d1 = fonction(1.0D);
        if(d < d1)
        {
            minY = d - 1.0D;
            maxY = d1 + 1.0D;
            vMin = d;
            xMin = 0.0D;
        } else
        {
            minY = d1 - 1.0D;
            maxY = d + 1.0D;
            vMin = d1;
            xMin = 1.0D;
        }
        points.clear();
    } // nouvelleFonction()
 
    protected void dichotomie()
    {
        if(points.size() > 0)
        {
            v = xMin;
            points.clear();
        } else
            v = 0.5D;
        DescenteGradient descentegradient = new DescenteGradient(this);
        double d = 0.5D / (double)dessin.getWidth();
        descentegradient.optimiser(0, valeur(), d);
        Collections.sort(points);
        repaint();
    } // dichotomie()
 
    protected void balayage()
    {
        points.clear();
        for(int i = 0; i < dessin.getWidth(); i++)
        {
            double d = (double)i / (double)dessin.getWidth();
            double d1 = fonction(d);
            if(d1 < vMin)
            {
                vMin = d1;
                xMin = d;
                minY = d1 - 1.0D;
            }
            maxY = Math.max(maxY, d1 + 1.0D);
            points.add(new Double(d));
        }
    } // balayage()
 
    public void actionPerformed(ActionEvent actionevent)
    {
        if(actionevent.getSource().equals(bNouvelleFonction))
            nouvelleFonction();
        if(actionevent.getSource().equals(bBalayage))
            balayage();
        if(actionevent.getSource().equals(bDichotomie))
            dichotomie();
        repaint();
    } // actionPerformed(ActionEvent)
 
    public void mouseClicked(MouseEvent mouseevent)
    {
        double d = (double)mouseevent.getX() / (double)dessin.getWidth();
        points.add(new Double(d));
        Collections.sort(points);
        double d1 = fonction(d);
        maxY = Math.max(maxY, d1 + 1.0D);
        if(d1 < vMin)
        {
            vMin = d1;
            xMin = d;
            minY = d1 - 1.0D;
        }
        repaint();
    } // mouseClicked(ActionEvent)
 
    public void mouseEntered(MouseEvent mouseevent)  {}
 
    public void mouseExited(MouseEvent mouseevent)   {}
 
    public void mousePressed(MouseEvent mouseevent)  {}
 
    public void mouseReleased(MouseEvent mouseevent) {}
 
    /******************
    * The Applet part *
    ******************/
    
    public void init()
    {
        nouvelleFonction();
        dessin = new JPanel() {
            protected void paintComponent(Graphics g)
            {
                int i = 0;
                int j = (int)((1.0D - (fonction(0.0D) - minY) / (maxY - minY)) * (double)getHeight());
                ListIterator listiterator = points.listIterator(0);
                g.setColor(Color.BLACK);
                while(listiterator.hasNext()) 
                {
                    Double double1 = (Double)listiterator.next();
                    int l = (int)(double1.doubleValue() * (double)getWidth());
                    int j1 = (int)((1.0D - (fonction(double1.doubleValue()) - minY) / (maxY - minY)) * (double)getHeight());
                    g.drawLine(i, j, l, j1);
                    i = l;
                    j = j1;
                }
                int k = getWidth();
                int i1 = (int)((1.0D - (fonction(1.0D) - minY) / (maxY - minY)) * (double)getHeight());
                g.drawLine(i, j, k, i1);
                g.setColor(Color.BLUE);
                int k1 = (int)(xMin * (double)getWidth());
                int l1 = (int)((1.0D - (vMin - minY) / (maxY - minY)) * (double)getHeight());
                g.drawOval(k1 - 2, l1 - 2, 5, 5);
            }
        }; // dessin = new JPanel()
	
        dessin.addMouseListener(this);
        bNouvelleFonction.addActionListener(this);
        boutons.add(bNouvelleFonction);
        bBalayage.addActionListener(this);
        boutons.add(bBalayage);
        bDichotomie.addActionListener(this);
        boutons.add(bDichotomie);
        pane.add(dessin, "Center");
        pane.add(boutons, "South");
        setContentPane(pane);
    } // init()
 
    public void start()   {}
 
    public void stop()    {}
 
    public void destroy() {}
 
    /*********************
    * The IFonction part *
    *********************/
 
    public double valeur()
    {
        double d = fonction(v);
        maxY = Math.max(maxY, d + 1.0D);
        if(d < vMin)
        {
            vMin = d;
            xMin = v;
            minY = d - 1.0D;
        }
        points.add(new Double(v));
        return d;
    } // valeur()
 
    public int nbParametres()
    {
        return 1;
    }
 
    public double[] domaine(int p) throws IllegalArgumentException
    {
        double ad[] = new double[2];
        ad[0] = 0.0D;
        ad[1] = 1.0D;
        return ad;
    } // domaine(p)
 
    public void regleParametre(int p, double d) throws IllegalArgumentException
    {
        v = d;
    }
 
    public double parametre(int i) throws IllegalArgumentException
    {
        return v;
    }
 
    public void printDescriptif(Writer writer, int i) throws IllegalArgumentException, IOException {}
 
    public void setReglage()   {}
 
    public void unsetReglage() {}
 
    /*********************
    * The variables part *
    *********************/
    
    protected JPanel pane;
    protected JPanel dessin;
    protected JPanel boutons;
    protected JButton bNouvelleFonction;
    protected JButton bBalayage;
    protected JButton bDichotomie;
    protected LinkedList points;
    protected double coeffs[];
    protected double maxY;
    protected double minY;
    protected double vMin;
    protected double xMin;
    protected double v;
} // class Bracketing