//benötigt gleichungssysteme2.js, matrixinvert.js

var G=new Array(),Vars=new Array("nix"),GV=new Array(),Ers=new Array(),Gi=new Array();
var G_=new Array(),Vars_=new Array("nix"),GV_=new Array(),Ers_=new Array();
var tErr="",tgls=new Array();
var nichtdiesekomb="";

//g:Gleichung, v: Liste aller Variablen des Gleichungssystems (String, getrennt mit Kommas oder Leerzeichen)
function regGl(g,vl)
{
	var i,j,k,gspl,t,v=vl.replace(/,/g," ").split(" "),vv="",vvv;
	if(g.indexOf("=")>-1){gspl=g.split("=");g=gspl[0]+"-("+gspl[1]+")";}
	g=" "+g.replace(/ +/g,"")+" ";
	var erg="()+-*/ %";
	for(i=1;i<g.length-1;i++)
	{
		if(erg.indexOf(g.charAt(i-1))==-1)continue;
		for(j=0;j<v.length;j++)
		{
			if((g.substr(i,v[j].length)==v[j])&&(erg.indexOf(g.charAt(i+v[j].length))>-1))break;
		}
		if(j==v.length)continue;
		g=g.substr(0,i)+"X["+j+"]"+g.substring(i+v[j].length,g.length);
		if((" "+vv).indexOf(" "+j+" ")==-1)vv+=j+" ";
	}
	g=g.replace(/X\[/g,"x[");
	G[G.length]=g;Gi[Gi.length]=Gi.length;
	Ers[Ers.length]=0;
	vvv=vv.substr(0,vv.length-1).split(" ");
	GV[GV.length]=new Array(vvv.length);for(i=0;i<vvv.length;i++)GV[GV.length-1][i]=vvv[i];
	if(Vars[0]=="nix")for(i=0;i<v.length;i++)Vars[i]=v[i];
	for(i=0;i<G.length;i++){G_[i]=G[i];Vars_[i]=Vars[i];GV_[i]=GV[i];Ers_[i]=Ers[i];}
	return g;
}

function Wiederherstellen()
{
	for(i=0;i<G_.length;i++){G[i]=G_[i];Vars[i]=Vars_[i];GV[i]=GV_[i];Ers[i]=Ers_[i];Gi[i]=i;}
}

//x: Werte, bekannt: Wert bekannt (boolean), x0...x1: Startwerte (jeweils Arrays)
//nmax: max. Anzahl der Unbekannten und Gleichungen

function solveSys(x,bekannt,x0,x1,nmin,nmax,versuche)
{
	var i=0;
	do
	{
		var vl;
		if((vl=solveSys_(x,bekannt,x0,x1,nmin,nmax,versuche))==null)break;
		nmin=vl.length;
		i++;
	}while(i<x.length);
}

function solveSys_(x,bekannt,x0,x1,nmin,nmax,versuche)
{
	if(nmin==null)nmin=1;
	if(nmax==null)nmax=Vars.length;
	if(versuche==null)versuche=5;
	var i,j,n,g,gv,k,v=new Array(G.length),t="",tt="";
	var xx=new Array(),xxx=new Array();
	for(i=0;i<G.length;i++)
	{
		for(j=0;j<Vars.length;j++)
		{
			if(bekannt[j])
			{
				if(G[i].indexOf("x["+j+"]")>-1)Ers[i]++;
				eval("G[i]=G[i].replace(/x\\["+j+"\\]/g,'("+x[j]+")')");
				eval("gv=((' '+GV[i].join(' ')+' ').replace(/ "+j+" /,' '))");
				GV[i]=gv.substring(1,gv.length-1).split(" ");
			}
			v[i]=gv;
		}
	}
	if(!Aufraeumen(false))return;
	if(G[0]=="")return null;
	//alert(GV.join("\n"));
	//alert(G.join("\n"));
	//n: Anzahl der Unbekannten (und Gleichungen)
	var KL=KombListeErzeugen();
	var KLn=KL.length
	for(n=nmin;n<=nmax;n++)
	{
		var komb=new Array(n),vll="";
		tgls=new Array(n);
		for(i=0;i<n;i++)komb[i]=i;
		status="Suche "+n+"x"+n+"-Gleichungssystem";
		do
		{
			if(komb[n-1]>=KLn)continue;
			if(KL[komb[n-1]]>=GV.length)continue;
			vl=Variablenliste(komb,KL);
			//alert(KL+"\n"+komb+"\n"+vl);
			if(vl!=null)
			if(n==vl.length)
			{
				Fkt=new Array(n);
				//t+="Gleichungen "+komb+";  Variablen: "+vl+";   ";
				vll="";
				for(j=0;j<n;j++)
				{
					Fkt[j]=G[KL[komb[j]]];tgls[j]=Gi[KL[komb[j]]];
					for(k=0;k<n;k++)eval("Fkt[j]=Fkt[j].replace(/x\\["+vl[k]+"\\]/g,'X["+k+"]')");
					Fkt[j]=Fkt[j].replace(/X/g,"x");//alert(G[KL[komb[j]]]+"\n"+vl+"\n"+Fkt[j]);
					vll+=Vars[vl[j]]+" ";
				}
				if(nichtdiesekomb.indexOf(tgls.join(" "))>-1)continue;
				//alert("x: "+x+"\nvl: "+vl+"\n\n"+Fkt.join("\n")+"\n\ntgls: "+tgls);
				status="Fand   "+n+"x"+n+"-Gleichungssystem - suche Lösung für Variablen "+vll;
				for(k=0;k<versuche;k++)
				{
					for(j=0;j<n;j++)xx[j]=x0[vl[j]]+Math.random()*(x1[vl[j]]-x0[vl[j]]);
					//alert(Fkt.join("\n")+"\n"+xx);
					var ns=solveGS(xx,n,50);
					//alert(ns+"\n"+xx);
					if((ns>0)&&(ns<50)&&(xx.join("").indexOf(NaN)==-1))
					{
						for(var jj=0;jj<5;jj++)
						{
							for(j=0;j<n;j++)xxx[j]=xx[j]+(Math.random()-.5)*(x1[j]-x0[j])/10;
							var ns1=solveGS(xxx,n,50);
							for(j=0;j<n;j++)if(Math.abs(xx[j]-xxx[j])>1e-5)break;
							if(j==n)break;
						}
						if(jj==5)break;
						//t+="("+ns+" Schritte):   "+xx.join("   ")+"\n";
						//var probe="";for(j=0;j<n;j++)probe+=f_(j,xx)+" = "+Fkt[j]+"\n";alert("Probe:\n"+probe);
						for(j=0;j<n;j++){x[vl[j]]=xx[j];bekannt[vl[j]]=true;}
						status="";
						return vl;
					}
				}
				status="Suche "+n+"x"+n+"-Gleichungssystem";
			}
		}while(nextKomb(komb,KL.length-1));
	}
	return null;
	
}

function Variablenliste(k,KL)
{
	var i,n=k.length,v=" "+GV[KL[k[0]]].join(" ")+" ";
	for(i=1;i<n;i++)
	{
		if(Ers[KL[k[i]]]==0)return null;
		for(j=0;j<GV[KL[k[i]]].length;j++)
		{
			if(GV[KL[k[i]]][j]=="")return null;
			if(v.indexOf(" "+GV[KL[k[i]]][j]+" ")==-1){v+=GV[KL[k[i]]][j]+" ";}
		}
	}
	return v.substring(1,v.length-1).split(" ");
}

function KombListeErzeugen()
{
	var i,j=0;
	KL=new Array();
	for(i=0;i<Ers.length;i++)if(Ers[i]!=0)KL[j++]=i;
	return KL;
}

function nextKomb(k,m)
{
	var n=k.length,i=n-1,j;
	k[n-1]++;
	while((k[n-1]>m)&&(i>=0))
	{
		i--;if(i==-1)break;
		k[i]++;
		for(j=i+1;j<n;j++)k[j]=k[j-1]+1;
	}
	if(k[n-1]>m)return false;
	return true;
}

function Aufraeumen(testen)
{
	var i,g="",gv="",t="",e="",gi="";
	for(i=0;i<G.length;i++)
	{
		if(G[i].indexOf("x[")>-1)
		{
			g+=G[i]+";";gv+=GV[i].join(" ")+";";e+=Ers[i]+";";gi+=Gi[i]+";";
			t+=G[i]+"   "+GV[i]+"\n";
		}
		else if(testen)
		{
			var y=eval(G[i]);if(Math.abs(y)>1e-5){tErr+=G[i]+" = "+y+"\n";return false;}
		}
	}
	G=g.substr(0,g.length-1).split(";");
	GV=gv.substr(0,gv.length-1).split(";");
	Ers=e.substr(0,g.length-1).split(";");
	Gi=gi.substr(0,gi.length-1).split(";");
	for(i=0;i<GV.length;i++)GV[i]=GV[i].split(" ");
	//alert(G.join("\n")+"----------\n"+GV.join("\n"));
	//alert("Nach Aufräumen:\n"+t);
	return true;
}

function test()
{
	var v="a b c wa wb wg A";
	regGl("a*a=b*b+c*c-2*b*c*Math.cos(wa)",v);
	regGl("A*A=(a+b+c)*(a+b-c)*(-a+b+c)*(a-b+c)/16",v);
	regGl("b*b=a*a+c*c-2*a*c*Math.cos(wb)",v);
	regGl("c*c=a*a+b*b-2*a*b*Math.cos(wg)",v);
	regGl("wa+wb+wg=3.14159265358979323/2",v);
	Absolutwert=true;
	solveSys(new Array(3,4,5,0,0,0,0),new Array(true,true,true,false,false,false,false),new Array(0,0,0,0,0,0,0),new Array(10,10,10,Math.PI,Math.PI,Math.PI,100),3,3);

}
