// PIMC oscillator,  Evgeny Demidov, 1 July 2004
import java.awt.*;
import java.awt.event.*;
public class pimc extends java.applet.Applet
 implements ActionListener{
  int  nt = 100, nt2=nt-2, np = 200, np2 = np/2, k = 1,
    w, h, h2, y0, lbSize = 50, it = 0, io, P[], stP=200;
  double x[], stX=.01;
  long generTime;
  Button btStep;

public void init() {
  w = getSize().width;  h = getSize().height - lbSize;
  h2 = h/2; y0 = h2 + lbSize;
  x = new double[nt];
  for (int i = 0; i < nt; i++) x[i] = 0;
  P = new int[np];
  for (int i = 0; i < np; i++) P[i] = 0;
  String s=getParameter("k"); if (s != null) k = Integer.parseInt(s);
  btStep = new Button("Step"); btStep.addActionListener(this); add(btStep);
  mc();
}

public void mc(){
  double dx, xnew, xr, ds;
  generTime = System.currentTimeMillis();
  io = 0;
  for (int i = 0; i < 1000000; i++){
   int r = (int)(nt*Math.random());
   if (r<1) r=1;   if (r>nt2) r=nt2;
   xr = x[r];
   dx = 1*(Math.random()-.5);   xnew = xr + dx;
   ds = dx*(2*(xnew+xr-x[r+1]-x[r-1]) + xnew+xr );
   if ( (ds<0) || (Math.random() < Math.exp(-ds)) ){
     x[r] = xr = xnew;  io++;}
   int l = (int)(30*xr) + np2;
   if (l>0 && l<np) P[l]++;}
  it++;
  generTime = System.currentTimeMillis()-generTime;
//   System.out.println(""+ds+"  "+Math.exp(-ds)+"  "+r+"   "+i);
}

public void paint(Graphics g) {
  g.setColor(Color.white);   g.fillRect(0, 0, w, h+lbSize);
  g.setColor(Color.black);   g.drawLine(0,y0 ,w,y0);
  int xt, x0=(int)(x[0]/stX)+y0;
  g.setColor(Color.red);
  for (int t = 1; t < nt; t++){
    xt = (int)(x[t]/stX) + y0;
    g.drawLine(3*(t-1),x0 ,3*t,xt);
    x0 = xt;}
  g.setColor(Color.blue);
  int pt, p0 = (int)(P[0]/(it*stP)) + 400, t0=y0-np2, t1=t0+1;
  for (int t = 1; t < np; t++){
    pt = (int)(P[t]/(it*stP)) + 400;
    g.drawLine(p0,t+t0, pt,t+t1);
    p0 = pt;}
  showStatus( "T=" + generTime +"   "+io );
}

public void actionPerformed(ActionEvent e){
  mc();  repaint();
}

public void update(Graphics g){ paint(g); }
}
