// import java.applet.*; import java.awt.*; import java.awt.event.*; public class Anteisei extends Applet implements ActionListener { //スクリーン private Image img; private Graphics gra; //ユーザーとのインターフェイス private double eps,q; private Label la1,la2; private TextField tf1,tf2; private Button bt1,bt2; private TextArea ta; //安定性解析の関数のためのパラメーター private double f; private double u,v; private double a,b,c,d; private double tr_A,det_A,D;//線形化して出来た行列 //二分法のためのパラメーター final private double EPS =1e-15;//打ち切り誤差 final private int limit=50;//打ち切り回数 private double low,mid,high; private int k=1; private double lastf,sol; //座標系の変換パラメーター private double ratiox,ratioy,X0,Y0; private int WX = 500, WY =500; //描画範囲 private double x_max = 10; private double x_min = -1; private double x_margin = (x_max-x_min)/10; private double y_max = 120; private double y_min = -20; private double y_margin = (y_max-y_min)/10; private boolean IsIn(double x, double y) { return (x_min <= x && x <= x_max && y_min <= y && y <= y_max); } // 座標変換の準備 private void space(double x0, double y0, double x1, double y1) { X0 = x0; Y0 = y0; ratiox = WX / (x1 - x0); ratioy = WY / (y1 - y0); } // ユーザー座標 (ワールド座標系) をウィンドウ座標 (デバイス座標系) private int wx(double x) { return (int)(ratiox * (x - X0)); } // ユーザー座標 (ワールド座標系) をウィンドウ座標 (デバイス座標系) private int wy(double y) { return WY - (int)(ratioy * (y - Y0)); } //tf からの数値読み取り private void ReadFields(){ eps = Double.valueOf(tf1.getText()).doubleValue(); q = Double.valueOf(tf2.getText()).doubleValue(); } //2乗の計算 private double sqr(double x){ return(x * x); } //判別式の関数 g1 private double g1(double f){ u = (1-f-q+Math.sqrt(sqr(f+q-1)+4*q*(1+f)))/2; v = u; a = (-2*u*u*u + (1 - 4 * q)*u*u + 2*q*(1-q)*u + q*(q-2*f*v))/(eps*sqr(q+u)); b = f*(q-u)/(eps*(q+u)); c = 1; d = -1; tr_A = a + d; det_A = a*d - b*c; D = sqr(tr_A) - 4*det_A; return D; } //固有方程式の根の関数 g2 private double g2(double f){ u = (1-f-q+Math.sqrt(sqr(f+q-1)+4*q*(1+f)))/2; v = u; a = (-2*u*u*u + (1 - 4 * q)*u*u + 2*q*(1-q)*u + q*(q-2*f*v))/(eps*sqr(q+u)); b = f*(q-u)/(eps*(q+u)); c = 1; d = -1; tr_A = a + d; det_A = a*d - b*c; D = sqr(tr_A) - 4*det_A; if(D>0) return (tr_A+Math.sqrt(D))/2; else return (tr_A)/2; } public void init() { //tf la bt のレイアウト setLayout(null); add(la1 = new Label("εの値:")); la1.setBounds (510,20,90,30); add(la2 = new Label("qの値:")); la2.setBounds (510,70,90,30); add(tf1 = new TextField(""+1e-2)); tf1.setBounds (610,20,80,30); add(tf2 = new TextField(""+8e-4)); tf2.setBounds (610,70,80,30); //Startボタン add(bt1 = new Button("Start")); bt1.addActionListener(this); bt1.setBounds (610,140,80,30); //Clearボタン add(bt2 = new Button("Clear")); bt2.addActionListener(this); bt2.setBounds (610,190,80,30); //TextArea add(ta =new TextArea(5,7)); ta.setBounds (510,280,180,220); //スクリーンの確保 img=createImage(WX,WY); gra=img.getGraphics(); gra.setColor(new Color(230,230,230)); gra.fillRect(0,0,WX,WY); //座標軸とます目 space(x_min-x_margin, y_min-y_margin , x_max+x_margin, y_max+y_margin); gra.setColor(Color.gray); for (double i=x_min; i<=x_max ; i=i+1){ gra.drawLine(wx(i),wy(y_min),wx(i),wy(y_max)); } for (double i=y_min; i<=y_max; i=i+10){ gra.drawLine(wx(x_min),wy(i),wx(x_max),wy(i)); } gra.setColor(Color.black); gra.drawLine(wx(x_min), wy(0.0), wx(x_max), wy(0.0)); gra.drawLine(wx(0.0), wy(y_min), wx(0.0), wy(y_max)); gra.drawString("0",wx(0.0),wy(0.0)); gra.drawString("5",wx(5),wy(0.0)); gra.drawString("10",wx(10),wy(0.0)); gra.setColor(Color.blue); gra.drawString("判別式のグラフ",120,20); gra.drawString("5000",wx(-1),wy(50)); gra.drawString("10000",wx(-1),wy(100)); gra.setColor(Color.red); gra.drawString("固有値の実部の最大値のグラフ",220,20); gra.drawString("50",wx(0),wy(50)); gra.drawString("100",wx(0),wy(100)); } public void paint(Graphics g){ update(g); } public void update(Graphics g){ g.drawImage(img,0,0,this); } public void actionPerformed(ActionEvent e) { if(e.getSource() == bt1) { //一つ前の点と今の点 double fx1,fx2; double fy1,fy2,fy3,fy4; //点を結ぶときの幅 double delta1 = 5e-5; space(x_min-x_margin, y_min-y_margin , x_max+x_margin, y_max+y_margin); ReadFields(); for(f=0; f<=x_max; f=f+delta1) { fx1=f-delta1; fx2=f; fy1=g1(f-delta1)/100; fy2=g1(f)/100; fy3 = g2(f-delta1); fy4 = g2(f); //判別式のグラフの表示 gra.setColor(Color.blue); if(IsIn(fx1,fy1) && IsIn(fx2,fy2)) { gra.drawLine(wx(fx1),wy(fy1),wx(fx2),wy(fy2)); fx1=fx2;fy1=fy2; } //固有方程式の根のグラフの表示 gra.setColor(Color.red); if(IsIn(fx1,fy3) && IsIn(fx2,fy4)) { gra.drawLine(wx(fx1),wy(fy3),wx(fx2),wy(fy4)); fx1=fx2;fy3=fy4; } } repaint(); double delta2 = 5e-2; //二分法による解の表示 for(double x=0; x<=x_max; x=x+delta2){ low=x; high=x+delta2; if( g1(low)*g1(high)<=0){ for (k=1;k<=limit;k++){ mid=(low+high)/2; if(g1(low)*g1(mid)<0) high=mid; else low=mid; if(g1(mid)==0 || Math.abs(high-low)limit){ ta.setText(ta.getText()+"収束しない"); } } } if ( g2(low)*g2(high)<=0){ for (k=1;k<=limit;k++){ mid=(low+high)/2; if(g2(low)*g2(mid)<0) high=mid; else low=mid; if(g2(mid)==0 || Math.abs(high-low)limit){ ta.setText(ta.getText()+"収束しない"); } } } } ta.setText(ta.getText()+sol+"