istest=false
btnlock=false
ans=""
txlimits=""
tylimits="auto"
hint=""
s_=""
sl_=""
slm_=""
sr_=""
srm_=""
s=""
BOUNDS=new Array(-1E199,1E199)
filename=""
xyv=new Array()

abse__=0
ymin_=1E199
ymax_=-1E199
sconstants=""
sdata=""
sxyzold=";;;"
sfunc=""
going=false
maxiter=10
paramlist=";"
is_apdata=true
vlist=";"
ulist=""
xyzlist="x y"
xyz=new Array("x","y")
xyzu=new Array("","")
slistnew=""
slistold=""
mainvlist=";Rg=0.08205783 /* L-atm/mol-K */;R=8.314 /* J/mol-K */;kb=1.38066e-23 /* J */;T=298 /* K */;P=1 /* atm */;V=1 /* L */;n=1 /* mol */;"
nq_=2
e=Math.E
n__=0
xfunc="x"
yfunc="y"
xlimits="from 0 to 10 step 1"
ylimits="from 0 to 10 step 1"
isfilelist=false


function dosimplex(mode)
{//-3 resetauto, -2 reset,-1 setup,1 go
 getinfo(mode>0)
 var s=""
 sl_=""
 slm_=""
 sr_=""
 srm_=""
 sresults=""
 nvars=0
 vlist=";"
 ulist=""
 havexyzs=0
 s__=mathof(smodel,mode)
 if(mode>0)updatemainvlist()
 sl_=smodel.substring(0,smodel.indexOf("="))
 slm_=s__.substring(0,s__.indexOf("="))
 sr_=smodel.substring(smodel.indexOf("=")+1,smodel.length)
 srm_=s__.substring(s__.indexOf("=")+1,s__.length)
 s__="("+strsub(s__,"=",")-(")+")"
 sm_="("+strsub(smodel,"=",")-(")+")"

 if (smodel.indexOf("=")<0)return alert("\n"+smodel+"="+eval(s__))
 if (nvars<=0)return alert("\n"+"No variables to optimize! \n"+sm_+"="+eval(s__))
 simplexsetup() 
 i=finditem(usr.syfunc,sl_,-1)
 if(i>=0)
 {
  usr.syfunc.selectedIndex=i
  usr.o_theory.checked=(np__!=2 || sr_!=Pinfo[0][0]+"*"+xyz[0]+"+"+Pinfo[1][0])
  usr.oytrendline.checked=!usr.o_theory.checked
  usr.tstheory.value=sr_
  for(i=0;i<usr.sxfunc.length;i++)
  {
   if(smodel.indexOf(usr.sxfunc.options[i])>=0)usr.sxfunc.selectedIndex=i
  }
 }
 if (np__>1 && !is_apdata)
 {
  vlist=strsub(vlist,"=;",";")
  simplexsetup()
 }
 var isdone=0
 if(mode==-3 && is_apdata)
 {
  var i0=true
  for(var i=1;i<xyz.length;i++)i0=i0&&(ulist.indexOf(","+xyz[i]+",")>=0?true:false)
  if(!i0)
  {
   alert("\n\nData do not appear to be appropriate to this function.\n\nIf you want to use this function with your data, change the names of the variables to match the equation.\n\nIf you want to use this function and solve for just one parameter or variable, indicate that you don't want to use data.")
   return
  }
 }
 if (np__==1 && !is_apdata  && Pinfo[0][0]==sl_)
 {
  eval(mainvlist)
  var e_=eval(srm_)
  if(!isNaN(e_))
  {
   isdone=-1
   Pinfo[0][1]=e_
   vlist=strsub(vlist,";"+Pinfo[0][0]+";",";")
   vlist=updatevlist(vlist,Pinfo[0][0],e_+"=",0)
   simplexsetup()
   usr.datavar.value=showlist(false)
   mainvlist=updatevlist(mainvlist,Pinfo[0][0],e_,0)
   eval(mainvlist)
   return 1
  }
 }
 usr.datavar.value=showlist(false)
 if (np__==0) 
 {
  var s="\n\nAll variables are marked as constants. Add an '=' after any you wish to allow to change.\n\n"
  if(havexyzs) return alert(s+"sigma^2 for "+sm_+" = "+evalV(-1))
  return alert(s+s__+"="+eval(s__))
 }
 if(mode<1) return "1"
 if((is_apdata?n__:0)+1<np__)return alert("\nNot enough data points for this optimization!")
 return dooptimize(isdone)
}
function simplexsetup()
{
 np__=0
 sconstants=""
 var s=mathclean(vlist)+";"
 var Va=s.split(";")
 paramlist=";"
 Pinfo=new Array() 
 Pnew=new Array()
 havenew=false
 for(var i=0;i<Va.length;i++)
 {
  var ieq=Va[i].indexOf("=")
  var ieq1=Va[i].lastIndexOf("=")
  if (ieq!=ieq1)Va[i]=Va[i].substring(0,ieq1)+"?"
  if(ieq<0){Va[i]+="=?";ieq=Va[i].length-2}
  if(ieq==Va[i].length-1){Va[i]+="?";ieq=Va[i].length-2}
  if (ieq>0 && Va[i].indexOf("?")>ieq)
  {
   Pinfo[np__]=Va[i].split("=")
   vlist=strsub(vlist,";"+Pinfo[np__][0]+";",";")
   paramlist+=";"+Pinfo[np__][0]+"="
   var s=Pinfo[np__][1]
   var iq=s.indexOf("?")
   if(iq<=0)
   {
    Pinfo[np__][1]=0
    Pnew[np__]=havenew=true
   }else{
    Pinfo[np__][1]=eval(s.substring(0,iq))
    Pnew[np__]=false
   }
   np__++
  }else{
   if(ieq>0)
   {
    var Vc=Va[i].split("=")
    s="="+eval(Vc[1])+";"
    vlist=strsub(vlist,"="+Vc[1]+";",s)
    sconstants+=Vc[0]+s
   }
  }
 }
 V_=new Array()
 Vok=new Array()
 eval(sconstants)
 if(np__==0)return 0
 vdim=np__+5
 V_=new Array(vdim)
 Vok=new Array(vdim)
 for(var j=0;j<vdim;j++)
 {
  V_[j]=new Array(np__+1)
  Vok[j]=1
 }
 for(var i=0;i<np__;i++)V_[0][i]=Pinfo[i][1]
 //V_[0] center (initially starting values)
 //V_[2] new1
 //V_[3] new2

 jnew1=2
 jnew2=3
 return np__ 
}

function randV(j)
{
 putV(0,j,1)
 for(var i=0;i<np__;i++)if(Pnew[i])V_[j][i]=Math.pow(e,Math.random()*20-10)
 return evalV(j)
}


function centV()//centroid
{
 for(var i=0;i<np__;i++)
 {
  V_[0][i]=0
  for(var j=2;j<vdim;j++){if(j!=jworst && Vok[j])V_[0][i]+=V_[j][i]}
  V_[0][i]=V_[0][i]/np__
 }   
}

function putV(ifrom,ito,scalar)
{
 for(var i=0;i<=np__;i++)V_[ito][i]=V_[ifrom][i]*scalar
}

function projV(j,j1)//project j to j1
{
 diffV(0,j,1)
 return contV(j,j1,2)
}

function diffV(j0,j1,j2)
{
 for(var i=0;i<np__;i++)V_[j2][i]=V_[j0][i]-V_[j1][i]
}

function contV(j,j1,scalar)
{
 for(var i=0;i<np__;i++)V_[j1][i]=V_[j][i]+V_[1][i]*scalar
 return evalV(j1)
}

function dotVs(j,j1)
{
 var e=0
 for(var i=0;i<np__;i++)e+=V_[j][i]*V_[j1][i]
 return e
}

function contVs()
{
 //NEW!!--why contract along OK coordinate?
 //semicontraction amounts to shear instead of shrink
 if(np__<3)
 {
  contV(jworst,jworst,.5)
 }else{
  //[1] holds projection vector Vp
  //we will take (V.Vp)/(Vp.Vp)*Vp/np__
  var e=dotVs(1,1)*np__
  for(var j=2;j<vdim;j++)
  {
   if(Vok[j])
   {
    diffV(0,j,jnew1)
    contV(j,j,dotVs(jnew1,1)/e)
   }
  }
 }
 jbest=bestV()
 jworst=worstV()
}

function bestV()
{
 var j1=0
 vbest=1E200
 for(var j=2;j<vdim;j++)
 {
  if(Vok[j]){if(V_[j][np__]<vbest){vbest=V_[j][np__];j1=j}}
 }
 return j1
}

function worstV()
{
 j1=0
 vworst=-1E200
 for(var j=2;j<vdim;j++)
 {
  if(Vok[j]){if(V_[j][np__]>vworst){vworst=V_[j][np__];j1=j}}
 }
 return j1
}

function getyrange()
{
 ymin_=1E199
 ymax_=-1E199
 for(var i__=0;i__<n__;i__++)
 {
  for(iq_=0;iq_<nq_;iq_++)eval(xyz[iq_]+"="+xyv[i__][iq_])
  var e__=eval(slm_)
  ymin_=Math.min(ymin_,e__)
  ymax_=Math.max(ymax_,e__)
 }
}
function initVs(nooffset)//V_[0] has starting points; V_[1] has offsets
{
 ymin_=-1E199
 ymax_=1E199
 if(havexyzs)getyrange()
 if(havenew)
 {
  jworst=0
  vworst=0
  randV(2)
  for(var i=0;i<20;i++)
  {
   for(var j=3;j<vdim;j++)randV(j)  
   jbest=bestV()
   putV(jbest,2,1)     
   ds+=".";status=ds
  }
  putV(jbest,0,1)
 }

 var sqr2=Math.pow(2,0.5)
 var q=(nooffset?0:(Math.pow(np__+1,0.5)-1)/sqr2/np__)
 for(var i=0;i<np__;i++)V_[1][i]=(V_[0][i]==0?1:V_[0][i])*0.097
 Vok[2]=Vok[3]=0
 for(var j=4;j<vdim;j++)
 {
  Vok[j]=1
  for(var i=0;i<np__;i++)V_[j][i]=V_[0][i]+(j==i+5?V_[1][i]:0)
 }   
 for(var i=0;i<np__;i++)V_[4][i]-=q
 for(var j=4;j<vdim;j++)evalV(j)
 jbest=bestV() 
 jworst=worstV()
 jnew1=2
 jnew2=3
 slistnew=""
 slistold=";"
 evalV(jbest)
 if (nooffset)return true
 return(jbest>0 && jworst>0 && jbest !=jworst && vworst>vbest)
}
function dumpVs(swhere)
{
 var s=swhere+"\nvbest "+vbest+"\nvworst "+vworst+"\nbest "+jbest+"\nworst "+jworst+"\nnew1 "+jnew1+"\nnew2 "+jnew2+"\n"
 for(var j=0;j<vdim;j++)s+=j+":"+Vok[j]+":"+V_[j]+"\n"
 alert(s)
 s=prompt("continue dumping?","yes")
 going=(s=="yes")
 istest=(s!="no")
}
function evalV(j__)
{
 var es__=0
 for(var i__=0;i__<np__;i__++)
 {
  var e__=V_[j__][i__]
  if(e__>=BOUNDS[0] && e__<=BOUNDS[1])
  {
   e__=Pinfo[i__][0]+"="+e__
   eval(e__)
  }else{
   es__=1E199
  }
 }
 if(es__==0)
 {
  if(havexyzs)
  {
   abse__=0
   for(var i__=0;i__<n__;i__++)
   {
    for(iq_=0;iq_<nq_;iq_++)eval(xyz[iq_]+"="+xyv[i__][iq_])
    var e__=eval(s__)
    abse__+=Math.abs(e__)
    es__+=e__*e__
   }
  }else{
   var e__=eval(s__)
   if (e__!=-(-e__)|| e__<-1e100)e__=-1e100
   es__+=e__*e__
  }
  if(isNaN(es__))es__=1E199
 }
 if(j__>=0)V_[j__][np__]=es__
 return es__
}

function newVs()
{
 niter++
 ds+=".";status=ds
 centV()
 var vs=projV(jworst,jnew1)
 if(istest)dumpVs("newVS prior to testing "+jnew1)
 if(vs<=vbest)
 {
  if(contV(jnew1,jnew2,1)<=vs)
  {
   jbest=jnew2
   jnew2=jnew1
  }else{
   jbest=jnew1
  }
  Vok[jbest]=1
 }else{//not new best
  if(vs>=vworst)
  {
   if(contV(jnew1,jnew2,-0.5)<vworst)
   {
    Vok[jnew2]=1
    jnew2=jnew1
   }else{
    contVs()
    return
   }
  }else{
   Vok[jnew1]=1
  }
 }
 jnew1=jworst
 Vok[jnew1]=0
 jworst=worstV()
 vbest=V_[jbest][np__]
 vworst=V_[jworst][np__]
 if(istest)dumpVs("looping")
}


function endop(msg,doupdate)
{
 going=false
 if(V_.length)setV(true)
 evalV(jbest)
 if(havexyzs && abse__> ymax_-ymin_)
 {
  msg+="\n\nNote: error is HUGE!\n"+abse__ + ">"+ymax_+"-"+ymin_ +"\nPressing 'Reset' and solving again will probably give a better solution."
 }else{
  updatemainvlist()
 }
 V_=new Array()
 vlist=""
 ulist=""
 status=""
 if(msg.length)alert("\n"+msg) 
 return 0
}

function dooptimize(mode)
{
 ds=""
 var ni=0
 if(mode<1)
 {
  niter=0
  if(!initVs(mode))return endop("Optimization is not possible from these starting conditions!\n\nPress 'Reset' and try again or estimate reasonable starting values followed by '='.",0)
  going=true
 }
 ds=""
 if(!going)return endop("Optimization halted after "+niter+" iterations.",0)
 if(vbest==0 || niter>0 && checkVs())return endop((niter==0?"":"Optimization finished after "+niter+" iterations."),0)
 while((ni!=maxiter) && going){ni++;newVs()}
 setV(false)
 return(going?setTimeout('dooptimize(1)',10):0)
}
function setV(isdone)
{
 for(var i=0;i<np__;i++)
 {
  var e=V_[jbest][i]
  Pinfo[i][1]=e
  vlist=updatevlist(vlist,Pinfo[i][0],e+"=",0)
 } 
 var Ndeg=(is_apdata?n__:2)-np__
 if(Ndeg==0)Ndeg=1
 if(isdone)
 {
  simplexerror=Math.pow(vbest,0.5)/Ndeg
 }else{
  e=0
  for(var j=2;j<vdim;j++){if(Vok[j])e+=V_[j][np__]}
  simplexerror=Math.pow(e,0.5)/Ndeg
 }
 vlist+="//"
 vlist=vlist.substring(0,vlist.indexOf("//"))
 vlist=updatevlist(vlist,"//sigma("+Ndeg+")",simplexerror,0)
 vlist=updatevlist(vlist,"//niter",niter,0)
 slistold=slistnew
 slistnew=vlist.substring(0,vlist.indexOf("//niter"))
 slistnew=strsub(slistnew,"=;",";")
 eval(slistnew)
 usr.datavar.value=sresults=showlist(true)
}
function checkVs()
{
 return (slistnew==slistold || vbest==0)
}
function updatemainvlist()
{
 vlist=";"+usr.datavar.value
 var s=vlist
 var i=s.indexOf("//BOUNDS=")
 BOUNDS=new Array(-1E199,1E199)
 if(i>=0)eval("BOUNDS=new Array"+s.substring(i+9,s.length))
 vlist=strsub(vlist,"\r","\n")
 vlist=strsub(vlist,"\n",";")
 vlist=mathclean(vlist)
 vlist=strsub(vlist,";;",";")+"//"
 vlist=vlist.substring(0,vlist.indexOf("//"))
 if(istest)alert(vlist)
 var Av=vlist.split(";")
 for(var i=0;i<Av.length;i++)
 {
  var sa=Av[i]
  if(sa.indexOf("?")<0)
  {
   if(sa.indexOf("=")>0 && sa.indexOf("=")<sa.length-1)
   {
    var AA=sa.split("=")
    mainvlist=updatevlist(mainvlist,AA[0],AA[1],0)
   }
  }
 }
 eval(mainvlist)
 return 0
}
function updatevlist(slist,svar,sval,usemain)
{
 var s=";"+svar+"="
 var sr=(usemain?varvalue(mainvlist,s):sval)
 if(usemain && sr.length && paramlist.indexOf(s)>=0)sr=(usemain==-2?"":sr+"=")
 var sl=slist
 var i=sl.lastIndexOf(s)
 if (i<0)
 {
  sl+=s.substring(1,s.length)+sr+";"
  return sl
 }
 sl=sl.substring(0,i)+s+sr+sl.substring(sl.indexOf(";",i+1),sl.length)
 return sl
}

function showlist(addlisting)
{
 var s=vlist
 s=strsub(s,"=?=","=")
 s=strsub(s,"=?","=")
 s=strsub(s,"==","=")
 s=strsub(s,";","\n")
 s=strsub(s,"\r","\n")
 s=strsub(s,"\n\n","\n")
 s=strsub(s,"'","")
 s=s.substring(1,s.length)
 s+="//BOUNDS=("+BOUNDS+")\n"
 if(addlisting && is_list)s+=dolist(0)
 return s
}

function varvalue(varlist,vdef)//vdef form is ";variable="
{
 var i=varlist.indexOf(vdef)
 if(i<0)return "?"
 return varlist.substring(i+vdef.length,varlist.indexOf(";",i+1))
}


