import java.awt.*;
import java.awt.event.*;
import java.awt.Graphics;
import java.util.*;
public class bp extends Frame implements ActionListener
{
public static final double max=10000000;
Label l1=new Label("请输入网络允许误差值:");
Label l2=new Label("请输入学习样本数目:");
Label l3=new Label("请选择学习因子:");
TextField t1,t2;
Button b1;
Choice c1;
boolean ok=false;
double e=0.5;
double n=0.4;
int num=500;
double w1[]=new double[10];
double w2[][]=new double[10][10];
double w3[]=new double[10];
double s1[]=new double[10];
double s2[]=new double[10];
double s3;
double o1[]=new double[10];
double o2[]=new double[10];
double o3;
double d1[]=new double[10];
double d2[]=new double[10];
double d3;
double dw1[]=new double[10];
double dw2[][]=new double[10][10];
double dw3[]=new double[10];

public static void main(String args[])
{
new bp();
}

bp()
{
this.setLayout(new FlowLayout());
t1=new TextField(5);
t1.setText("0.5");
t2=new TextField(5);
t2.setText("500");
b1=new Button("开始");
c1=new Choice();
c1.addItem("0.1");
c1.addItem("0.2");
c1.addItem("0.3");
c1.addItem("0.4");
c1.addItem("0.5");
c1.addItem("0.6");
c1.addItem("0.7");
c1.addItem("0.8");
c1.addItem("0.9");
c1.select(3);
this.add(l1);
this.add(t1);
this.add(l2);
this.add(t2);
this.add(l3);
this.add(c1);
this.add(b1);
t1.addActionListener(this);
t2.addActionListener(this);
b1.addActionListener(this);
addWindowListener(new close());
this.setTitle("用bp算法模拟标准正弦函数");
this.setSize(600,600);
this.setLocation(100,100);
this.setVisible(true);
}

public void paint(Graphics g)
{

drawxy(g,5,45,300);
g.setColor(Color.blue);
drawsinx(g,5,45,300);
g.setColor(Color.red);
if(ok)
drawbpf(g,5,45,300); }

public void drawsinx(Graphics g,int l,int x,int y)
{
l*=100;
((Graphics2D)g).setStroke(new BasicStroke(1));
for(int i=0;i<l;i++)
g.drawLine(i+x,-(int)Math.round(sinx(i*0.01)*100)+y,i+1+x,-(int)Math.round(sinx((i+1)*0.01)*100)+y);
}

public void drawbpf(Graphics g,int l,int x,int y)
{
l*=100;
((Graphics2D)g).setStroke(new BasicStroke(1));
for(int i=0;i<l;i++)
g.drawLine(i+x,-(int)Math.round(bpf(i*0.01)*100)+y,i+1+x,-(int)Math.round(bpf((i+1)*0.01)*100)+y);
}

public void drawxy(Graphics g,int l,int x,int y)
{
l*=100;
((Graphics2D)g).setStroke(new BasicStroke(3));
g.setColor(Color.black);
g.drawLine(x,y,x+l+30,y);
g.drawLine(x+l+20,y+5,x+l+30,y);
g.drawLine(x+l+20,y-5,x+l+30,y);
g.drawLine(x,y+120,x,y-120);
g.drawLine(x+5,y-110,x,y-120);
g.drawLine(x-5,y-110,x,y-120);
g.drawLine(x,y-100,x+5,y-100);
g.drawLine(x,y+100,x+5,y+100);
g.setFont(new Font(g.getFont().getName(),Font.BOLD,20));
g.drawString("x",x+l+30,y+20);
g.drawString("y",x-20,y-120);
g.drawString("1",x-20,y-90);
g.drawString("0",x-20,y+15);
g.drawString("-1",x-25,y+110);
for(int i=1;i<=l;i++)
{
if(i%100==0)
{
g.drawString(i/100+"",i+x-10,y+20);
g.drawLine(i+x,y,i+x,y-5);
}
}
}

public double sinx(double x)
{
double y;
y=Math.pow(Math.sin(x*5*Math.PI),6);
return y;
}

public double bpf(double x)
{
int i,j;
for(i=0;i<o1.length;i++)
o1[i]=0;
for(j=0;j<o2.length;j++)
o2[j]=0;
o3=0;
for(i=0;i<o1.length;i++)
{
o1[i]=x*w1[i]-s1[i];
o1[i]=1/(1+Math.exp(-o1[i]));
}
for(j=0;j<o2.length;j++)
{
for(i=0;i<o1.length;i++)
{
o2[j]+=o1[i]*w2[i][j];
}   
o2[j]-=s2[j]; 
o2[j]=1/(1+Math.exp(-o2[j]));
}
for(i=0;i<o2.length;i++)
{
o3+=o2[i]*w3[i];
}
o3-=s3;
o3=1/(1+Math.exp(-o3));
return o3;
}

public void init()
{
int i,j;
for(i=0;i<o1.length;i++)
{
w1[i]=Math.random();
s1[i]=Math.random();
o1[i]=0;
}
for(j=0;j<o2.length;j++)
{
for(i=0;i<o1.length;i++)
{
w2[i][j]=Math.random();
}   
s2[j]=Math.random(); 
o2[j]=0;
}
for(i=0;i<o2.length;i++)
{
w3[i]=Math.random();
}   
s3=Math.random();
o3=0;
}

public void study()
{
double E,Ep,lastE,x,y;
int N,i,j,count1,count2;
lastE=0;
count1=0;
count2=0;
do
{
E=0;
for(i=0;i<dw1.length;i++)
dw1[i]=0;
for(i=0;i<dw2.length;i++)
for(j=0;j<dw2[0].length;j++)
dw2[i][j]=0;
for(i=0;i<dw3.length;i++)
dw3[i]=0;
x=0;
for(N=0;N<500;N++,x+=0.01)
{
y=sinx(x);
Ep=Math.pow(y-bpf(x),2)/2.0;
E+=Ep;
d3=o3*(1-o3)*(y-o3);
for(i=0;i<o2.length;i++)
{
dw3[i]+=n*d3*o2[i];
d2[i]=o2[i]*(1-o2[i])*w3[i]*d3;
}
for(i=0;i<o1.length;i++)
for(j=0;j<o2.length;j++)
{
dw2[i][j]+=n*d2[j]*o1[i];
d1[i]+=o1[i]*(1-o1[i])*w2[i][j]*d2[j];
}
for(i=0;i<o1.length;i++)
{
dw1[i]+=n*d1[i]*x;
}
}
for(i=0;i<w1.length;i++)
w1[i]+=dw1[i];
for(j=0;j<w2[0].length;j++)
for(i=0;i<w2.length;i++)
w2[i][j]+=dw2[i][j];
for(i=0;i<w3.length;i++)
w3[i]+=dw3[i];
E=E/2.0;
if(E==lastE)
count1++;
if(count1>=5)
{
lastE=0;
count1=0;
count2=0;
init();
continue;
}
lastE=E;
count2++;
}while((E>e)&&(count2<10000));
}

public void actionPerformed(ActionEvent E)
{
if(E.getSource()==b1)
{
e=Double.valueOf(t1.getText()).doubleValue();
num=Integer.parseInt(t2.getText());
n=(c1.getSelectedIndex()+1)*0.1;
init();
study();
ok=true;
repaint();
}

}
}
class close extends WindowAdapter
{
public void windowClosing(WindowEvent E)
{
Frame f=(Frame)(E.getSource());
f.dispose();
System.exit(0);
}
}