////////// FEEL FREE TO INSERT THE DESIRED VALUES HERE ////////////////////////////////
int inputs=9, chainlength=15;
// The number of x-variables and the number of non-empty cells in the Wenn diagram
int MAXGATEINPUT=3;
//the maximal number of allowed inputs for AND, OR, NAND, NOR
int MAXHEAPSIZE=700;
bool verbose=true;
//Whether you want to see the building process step by step
bool randommode=false;
//Random generation of the decreasing sequences in the range [1,2^inputs-1]
bool statistics=true;
//To see the distribution of results over the runs
bool circuit=true, rawcircuit=false;
//To output the final circuit
int MM=1000;
//The number of random runs
int[] sample={471,448,438,384,326,282,264,248,204,144,102,46,24,16,8};
//124 118 68 53 22 4
//Insert the sequence you want to see it realized here
if(randommode==false) chainlength=sample.length;
sample=reverse(sort(sample));
if(!randommode && sample[0]>2^inputs) {write("Unfeasible; not enough space!"); pause(); exit();}
if(!randommode && sample[0]==2^inputs) {write("You don't need that long chain: A[1]=TRUE"); pause(); exit();}
//just to prevent a crash for an idiotic reason
////////////////////////////////////////////////////////////////////////////////////////
/*
Asymptote also defnes bitwise functions int AND(int,int), int OR(int,int),
int XOR(int,int), int NOT(int), int CLZ(int) (count leading zeros), int CTZ(int)
(count trailing zeros), int popcount(int) (count bits populated by ones)
*/
int[][] assembly=
{
{},
{1},
{1,2},
{1,3,2},
{1,3,2,4},
{2,3,1,5,4},
{5,1,3,2,6,4},
{7,5,1,3,2,6,4},
{7,5,1,3,2,6,4,8},
{7,5,4,6,2,3,1,9,8}
};
//Can you see the pattern? I'm too stupid to discern it yet, so I'll play a bit more with small values...
int FAILCOUNT=0;
int BUILD(int length)
{
return 0;
if(length<10)
{
int t=length-1;
if(popcount(length)==1) ++t;
return 2t;
}
else return 2(chainlength-1+ceil(4*max(chainlength-7,0)/7));
//The cost for the final assembly.
//We'll figure the correct values for length>9 later. This is just a crude approximation
//that may be a couple of gates off in your range.
}
//The count for the final assembly stage (not programmed yet)
//In the rest I just replaced 7 by chainlength and 8 by inputs (but be careful: some 7 were actually 8-1 :lol:)
int N=0,NN=0, COUNT=0, GATE3COUNT=0;
int red=min(inputs,5), RED=2^red;
int Q=2^(inputs-red); int ONES=2^RED-1;
int NOTTT(int q)
{
return AND(ONES,NOT(q));
}
int[] ss; for(int k=0;k<400;++k) ss[k]=0;
int cost=Q, ref=Q+1, op=Q+2, name=Q+3, anmbr=Q+4, args=Q+5, arg1=args, arg2=args+1;
string[] oper={"AND","OR","NAND", "NOR", "NOT","INPUT","BRED","BRED"};
string[] named={"X","U","A","B","FALSE","TRUE","BRED"};
int
andd=0, orr=1, nandd=2, norr=3, nott=4,
inputt=5, varr=0, auxx=1,outt=2,outnott=3, falst=4, truee=5,
upp=0, downn=1;
int REF=1;
int[] opcost={3,3,2,2,1,0};
srand(seconds());
int[][] comb(int[][] W)
{
int[][] WW=copy(W);
int N=W.length;
int F(int q)
{
for(int k=0;k<N;++k) if(W[k][ref]==q) return k+1;
return 0;
}
for(int k=0;k<N;++k)
{
WW[k][ref]=k+1;
for(int arg=args; arg<WW[k].length; ++arg)
WW[k][arg]=F(W[k][arg]);
}
//write("comb finished");
return WW;
}
void print(int[][] W)
{
for(int k=0;k<W.length;++k)
{
string s="";
s+=string(k+1)+" : "+string(W[k][ref])+ "="
+oper[W[k][op]];
s+="(";
for(int arg=args; arg<W[k].length;++arg)
{
if(arg==args) s+"(";
s+=string(W[k][arg]);
if(arg<W[k].length-1) s+=",";
if(arg==W[k].length-1) s+=")";
}
s+=" used as "+ named[W[k][name]]
+(W[k][name]==outt || W[k][name]==outnott? string(W[k][anmbr]):"");
write(s);
}
//pause();
}
void disp(int[][] W)
{
int[][] WW=copy(W);
int[] cnt={1,1,1};
for(int k=0;k<W.length;++k)
{
int u=W[k][name]; if (u==falst || u==truee) u=varr;
if(W[k][name]==outt|| W[k][name]==outnott) WW[k][ref]=W[k][anmbr]; else {WW[k][ref]=cnt[u]; ++cnt[u];}
}
string s="";
int inputts=inputs+2;
for(int k=inputts;k<W.length;++k)
{
s+=string(k-inputts+1)+ " : ";
int u=W[k][name];
s+=named[u]+"["+string((u==outt || u==outnott? W[k][anmbr]:WW[k][ref]))+"] = "+oper[W[k][op]]+"(";
for(int arg=args; arg<W[k].length; ++arg)
{
u=W[k][arg];
if(u>0) s+=named[W[u-1][name]]+(W[u-1][name]==falst || W[u-1][name]==truee? "" : "["+string(WW[u-1][ref])+"]");
if(arg<W[k].length-1) s+=",";
}
s+=')\n';
}
write(s);
write("");
//pause();
}
int[] AA(int[][] W, int ccount)
{
int costcount=BUILD(chainlength);
int[] gg, ggnott; for(int k=0;k<chainlength;++k) {gg[k]=0; ggnott[k]=0;}
for(int q=0;q<2^inputs;++q)
{
bool[] u; int qq=q;
for(int k=0;k<inputs;++k) {u[k]=(qq%2==1); qq=quotient(qq,2);}
u[inputs]=false; u[inputs+1]=true;
//if(q==137) for(int k=0;k<inputs;++k) write(string(k)+" "+(u[k]?"true":"false"));
int inputts=inputs+2;
for(int k=inputts; k<W.length; ++k)
{
if(W[k][op]==nott) {u[k]=!u[W[k][args]-1]; if(q==0) costcount+=opcost[nott];}
if(W[k][op]==inputt) {u[k]=u[W[k][args]-1]; if(q==0) costcount+=opcost[inputt];}
bool currand=true, curror=false;
for(int arg=args; arg<W[k].length; ++arg)
{
currand=currand && u[W[k][arg]-1];
curror=curror || u[W[k][arg]-1];
}
if(W[k][op]==andd) {u[k]= currand; if(q==0) costcount+=opcost[andd]+W[k].length-args-2;}
if(W[k][op]==orr) {u[k]= curror; if(q==0) costcount+=opcost[orr]+W[k].length-args-2;}
if(W[k][op]==nandd) {u[k]= !currand; if(q==0) costcount+=opcost[nandd]+W[k].length-args-2;}
if(W[k][op]==norr) {u[k]= !curror; if(q==0) costcount+=opcost[norr]+W[k].length-args-2;}
//if(q==137) write(string(k)+" "+(u[k]?"true":"false"));
if(W[k][name]==outt){if(u[k]) ++gg[W[k][anmbr]-1];}
if(W[k][name]==outnott){if(u[k]) ++ggnott[W[k][anmbr]-1];}
}
//if(q==137) pause();
}
for(int k=0;k<gg.length;++k)
if(gg[k]+ggnott[k]!=Q*RED)
{write("Misnegation!"); write(gg,ggnott); pause();}
if(costcount!=ccount) {write("Cost miscalculation!"); write(costcount, ccount); pause();}
return(gg);
}
int summ(int[] A)
{
int s=0;
for(int q=0;q<Q;++q)
s+=popcount(A[q]);
return s;
}
bool LESS(int[] A, int[] B)
{
return A[cost]<B[cost];
}
int[] COPY(int[] A)
{
int[] C; for(int q=0;q<Q;++q) C[q]=A[q];
C[ref]=REF;
C[op]=inputt;
C[arg1]=A[ref]; C[name]=auxx; C[cost]=opcost[inputt];
++REF;
return C;
}
int[] ANDD(int[] A, int[] B)
{
int[] C; for(int q=0;q<Q;++q) {C[q]=AND(A[q],B[q]);}
C[ref]=REF;
C[op]=andd;
C[arg1]=A[ref]; C[arg2]=B[ref]; C[name]=auxx; C[cost]=opcost[andd];
++REF;
return C;
}
int[] ORR(int[] A, int[] B)
{
int[] C; for(int q=0;q<Q;++q) C[q]=OR(A[q],B[q]);
C[ref]=REF; C[op]=orr; C[arg1]=A[ref]; C[arg2]=B[ref]; C[name]=auxx; C[cost]=opcost[orr];
++REF;
return C;
}
int[] NORR(int[] A, int[] B)
{
int[] C; for(int q=0;q<Q;++q) C[q]=NOTTT(OR(A[q],B[q]));
C[ref]=REF; C[op]=norr;
C[arg1]=A[ref]; C[arg2]=B[ref]; C[name]=auxx; C[cost]=opcost[norr];
++REF;
return C;
}
int[] NANDD(int[] A, int[] B)
{
int[] C; for(int q=0;q<Q;++q) {C[q]=NOTTT(AND(A[q],B[q]));}
C[ref]=REF;
C[op]=nandd;
C[arg1]=A[ref]; C[arg2]=B[ref]; C[name]=auxx; C[cost]=opcost[nandd];
++REF;
return C;
}
int[] Sstrt, Sup, Sdown,Sa;
bool EQ(int[] A, int[] B)
{
bool flag=true;
for(int q=0;q<Q && flag;++q)
{
if(AND(A[q],Sdown[q])!=AND(B[q],Sdown[q])) flag=false;
if(AND(A[q],NOTTT(Sup[q]))!=AND(B[q],NOTTT(Sup[q]))) flag=false;
}
return flag;
}
int IND(int[] A, int[][] W)
{
int ind=-1, ccost=10000;
bool flag=true;
for(int k=0; k<W.length; ++k)
{
if(EQ(A,W[k]) && W[k][cost]<ccost) {ind=k; ccost=W[k][cost];}
}
return ind;
}
bool NEW(int[] A, int[][] W)
{
bool flag=true;
int ind=IND(A,W);
if(ind>=0 && W[ind][cost]<=A[cost]) flag=false;
return flag;
}
int[] REPORT(int[][] H)
{
int[] R={0,0,0,0};
for(int k=0;k<H.length;++k) ++R[H[k][cost]];
return R;
}
int[][] purge(int[][] H, int[][] W, int START)
{
int[][] S=copy(H[0:START]);
for(int k=START;k<H.length;++k)
{
if(NEW(H[k],S) && IND(H[k],W)<0) S[S.length]=copy(H[k]);
}
if(verbose) write(string(H.length-S.length)+" entries removed from H as costlier duplicates");
return S;
}
int[] NOTT(int[] A)
{
int[] C; for(int q=0;q<Q;++q) C[q]=NOTTT(A[q]);
C[ref]=REF; C[op]=nott; C[arg1]=A[ref]; C[name]=auxx; C[cost]=opcost[nott];
++REF;
return C;
}
int EXTRAARGNUM(int[] A){return max(0,A.length-args-2);}
int[] NCONVERT(int[] A)
{
if(A[op]!=andd && A[op]!=orr) return copy(A);
int[] C; for(int q=0;q<Q;++q) C[q]=NOTTT(A[q]);
C[ref]=REF;
if(A[op]==orr) C[op]=norr;
if(A[op]==andd) C[op]=nandd;
for(int arg=args; arg<A.length; ++arg) C[arg]=A[arg];
C[cost]=opcost[C[op]]+EXTRAARGNUM(C);
C[name]=auxx;
++REF;
return C;
}
int[] ADJ(int[] A, int[] B) //Adding B to the list of arguments of A
{
if(A[op]!=andd && A[op]!=orr) return copy(A);
if(EXTRAARGNUM(A)==MAXGATEINPUT-2) return copy(A);
int[] C; for(int q=0;q<Q;++q) C[q]=(A[op]==andd ? AND(A[q],B[q]) : OR(A[q],B[q]));
C[ref]=REF;
C[op]=A[op];
for(int arg=args; arg<A.length; ++arg) C[arg]=A[arg]; C[C.length]=B[ref];
C[cost]=opcost[C[op]]+EXTRAARGNUM(C);
C[name]=auxx;
++REF;
return C;
}
int[] NADJ(int[] A, int[] B) //Adding B to the list of arguments of A
{
if(A[op]!=nandd && A[op]!=norr) return copy(A);
if(EXTRAARGNUM(A)==MAXGATEINPUT-2) return copy(A);
int[] C; for(int q=0;q<Q;++q) C[q]=(A[op]==nandd ? NOTTT(AND(NOTTT(A[q]),B[q])) : NOTTT(OR(NOTTT(A[q]),B[q])) );
C[ref]=REF;
C[op]=A[op];
for(int arg=args; arg<A.length; ++arg) C[arg]=A[arg]; C[C.length]=B[ref];
C[cost]=opcost[C[op]]+EXTRAARGNUM(C);
C[name]=auxx;
++REF;
return C;
}
int[] FALSE;
for(int k=0;k<Q;++k) FALSE[k]=0;
FALSE[op]=inputt; FALSE[ref]=REF; FALSE[name]=falst; FALSE[args]=0; FALSE[cost]=opcost[inputt]; ++REF;
int[] TRUE;
for(int k=0;k<Q;++k) TRUE[k]=ONES;
TRUE[op]=inputt; TRUE[ref]=REF; TRUE[name]=truee; TRUE[args]=0; TRUE[cost]=opcost[inputt]; ++REF;
int[][] DIG;
for(int k=0; k<inputs; ++k)
{
DIG[k]=new int[];
int[] dig;
for(int q=0;q<Q2^inputs;++q) dig[q]=quotient(q,2^(inputs-1-k))%2;
for(int q=0;q<Q;++q)
{
int r=0, u=1; for(int s=0;s<RED;++s) {r+=dig[REDq+s]u; u=2;}
DIG[k][q]=r;
}
DIG[k][ref]=REF; DIG[k][op]=inputt; DIG[k][args]=0; DIG[k][name]=varr; DIG[k][cost]=opcost[inputt];
++REF;
}
DIG[inputs]=FALSE;
DIG[inputs+1]=TRUE;
int[][] LSTORD;
LSTORD[0]=new int[]; for(int k=0; k<inputs; ++k) LSTORD[0][k]=k;
for(int m=0;m<=inputs;++m)
{
LSTORD[m]=copy(LSTORD[0]);
for(int vv=0; vv<inputs^2; ++vv)
{
int i=rand()%inputs, j=rand()%inputs;
int t=LSTORD[m][i]; LSTORD[m][i]=LSTORD[m][j]; LSTORD[m][j]=t;
}
}
int[][] NLST(int a, int ord, int[][] W, int[][] H, bool thorough=false, int maxlength=inputs)
{
int[][] LST;
if(a==0)
{
LST[0]=copy(FALSE);
}
else
{
int[] eps;
int b=a%(QRED);
int kk=inputs-1;
if(a<QRED) while(b%2==0) {b=quotient(b,2); --kk;}
if(a<Q*RED)
{
while(kk>0)
{
if(b>=2^kk){eps[eps.length]=0; b=2^(kk+1)-b;}
else{eps[eps.length]=1; b=2^kk-b;}
--kk;
}
}
else
{
while(kk>0)
{
eps[eps.length]=(eps.length+inputs+b)%2; b=quotient(b,2);
--kk;
}
}
int k=min(eps.length,maxlength); int kk=k;
if(a<2QRED) LST[k]=copy(DIG[LSTORD[ord][kk]]);
else if(a<3QRED)
{
LST[k]=copy(FALSE);
}
else LST[k]=copy(TRUE);
while(k>0)
{
--k;
--kk;
LST[k]=(eps[k]==0?NANDD(DIG[LSTORD[ord][kk]],LST[k+1]):NORR(DIG[LSTORD[ord][kk]],LST[k+1]));
//write(LST[k]); write("DIG?"); pause();
if(thorough)
{
int ind=IND(LST[k],W);
if(ind>=0 && k<LST.length-1) {LST[k]=copy(W[ind]); LST=LST[0:k+1];}
ind=IND(LST[k],H);
if(ind>=0 && k<LST.length-2) {LST[k]=copy(H[ind]); LST=LST[0:k+2];}
}
}
}
if(LST.length==1) {LST[1]=copy(LST[0]); LST[0]=COPY(LST[1]);}
return LST;
}
int SHOOT(int aa, int dirr, int ord, int[][] W={}, int[][] H={},int maxlength=inputs)
{
if(dirr==upp) return summ(ORR(Sup,NLST(aa,ord,W,H,maxlength)[0]));
if(dirr==downn) return summ(ANDD(Sdown,NLST(aa,ord,W,H,maxlength)[0]));
write("Invalid request!");
return -1;
}
int QQ=QRED;
int[] CHAIN={2QQ, QQ, 3*QQ};
for(int k=1;k<inputs;++k)
{
int N=CHAIN.length;
for(int q=0; q<N;++q)
{
int quot=quotient(CHAIN[q],QQ); if(quot>1) quot=5-quot;
CHAIN[2*N-1-q]=quot*QQ+2^(inputs-k-1)+2^(inputs)-2^(inputs-k)-CHAIN[q]%QQ;
}
}
if(inputs%2==0) CHAIN=reverse(CHAIN);
int NEXT(int k, int m)
{
if(m%2==1)
{int kk=k; if(kk%(32^(m-1))==2) {kk-=2; kk+=32^(m-1);} else ++kk; return kk;}
else {int kk=k; if(kk%(32^(m-1))==0) {kk+=2; kk+=32^(m-1);} else --kk; return kk;}
}
int LSTARG(int goal, int dirr, int ord, int maxlength=inputs-1)
{
int m=1; inputs-maxlength;
int[] CHN; for(int k=2*((m+1)%2); k<CHAIN.length; k=NEXT(k,m)) CHN[CHN.length]=CHAIN[k];
int a=0, b=CHN.length-1, try=-1;
while(a<b)
{
int c=quotient(a+b,2), try=SHOOT(CHN[c], dirr, ord);
if(try>=goal) b=c; else a=min(b,c+1);
}
if(SHOOT(CHN[a],dirr,ord,maxlength)==goal) return CHN[a]; else return -1;
}
struct T{int cost; int ord; string dirr; int start; int length;}
T CHECKINTCOST(int qup, int qdown, int[] a, int[][] W, int[][]H, bool thorough=false)
{
int bestord=0, bestcost=100000, beststart, bestlength;
string dirr;
if(verbose) write("started check with qup="+string(qup)+" qdown="+string(qdown));
for(int ord=0; ord<(thorough?LSTORD.length:LSTORD.length);++ord)
for(int maxlength=1; maxlength<inputs;++maxlength)
{
//if(verbose) write(ord);
int ccost=10000;
if(qdown<chainlength)
{
int aa=LSTARG(a[qdown],downn,ord,maxlength);
if(aa>=0)
{
int[][] WA=NLST(aa,ord,W,H,true,maxlength);
ccost=0; for(int k=0;k<WA.length-1;++k) ccost+=WA[k][cost];
if(ccost<bestcost) {bestcost=ccost; bestord=ord; dirr="down"; beststart=aa; bestlength=maxlength;}
}
}
if(qup>=0)
{
int aa=LSTARG(a[qup],upp,ord,maxlength);
if(aa>=0)
{
int[][] WA=NLST(aa,ord,W,H,true,maxlength);
ccost=0; for(int k=0;k<WA.length-1;++k) ccost+=WA[k][cost];
if(ccost<bestcost) {bestcost=ccost; bestord=ord; dirr="up"; beststart=aa; bestlength=maxlength;}
}
}
//write(maxlength,ccost,bestcost);
}
if(verbose) write("ended check with beststart="+string(beststart));
if(bestcost>100) pause();
T S=new T;
S.cost=bestcost+opcost[andd]; S.ord=bestord; S.dirr=dirr; S.start=beststart; S.length=bestlength;
return S;
}
for(int mm=0; mm<(randommode? MM:1); ++mm)
{
int[] a;
int[] str; for(int k=0;k<QRED;++k) str[k]=0;
int kk=0;
while(kk<chainlength) {int r=rand()%(QRED-1)+1; if(str[r]==0) {str[r]=1;++kk;}}
kk=0;
for(int k=Q*RED-1;k>=0;--k) if(str[k]==1) {a[kk]=k;++kk;}
int ccount=100000;
int[][] Wopt;
for(int qstrt=0; qstrt<chainlength; ++qstrt)
{
int qqq=0;
write("attempt starting with A"+string(qstrt+1));
int m=0, count=BUILD(chainlength); int[][] W,H;
for(int k=0;k<DIG.length;++k) W[k]=copy(DIG[k]);
if(! randommode) a=copy(sample);
string s="";
for(int k=0;k<chainlength;++k) s+=string(a[k])+" "; if(verbose || qstrt==0) write(s);
for(int q=0;q<Q;++q) {Sup[q]=0; Sdown[q]=ONES;}
void APPENDNOTT(int[] X, int qqq)
{
W[W.length]=copy(X); count+=X[cost];
W[W.length-1][name]=outnott; W[W.length-1][anmbr]=qqq+1;
}
int[][] WA=copy(NLST(a[qstrt],0,W,H));
for(int k=WA.length-2;k>=0;--k)
{
W[W.length]=copy(WA[k]);
count+=WA[k][cost];
}
Sstrt=copy(WA[0]); Sup=copy(WA[0]); Sdown=copy(WA[0]);
W[W.length-1][name]=outt; W[W.length-1][anmbr]=qstrt+1;
APPENDNOTT(NOTT(W[W.length-1]),qstrt);
int qdown=qstrt+1, qup=qstrt-1;
if(verbose) write("done with choice 1 with count="+string(count)+" W="+string(W.length)+" H="+string(H.length)
+" we have "+string(summ(Sstrt))+"="+string(a[qstrt]));
int WLENOLD=0;
for(int qq=chainlength-2; qq>=0; --qq)
{
bool flag=true;
int qupold=qup, qdownold=qdown;
void APPEND(int[] X, int dir, bool flagg=true)
{
if(flag && dir==upp)
{
int[] Y=NORR(Sup,X), Z=NOTT(Y);
if(flagg) {W[W.length]=copy(X); count+=X[cost];}
W[W.length]=copy(Y);
W[W.length-1][name]=outnott; W[W.length-1][anmbr]=qup+1;
W[W.length]=copy(Z); Sup=copy(Z);
W[W.length-1][name]=outt; W[W.length-1][anmbr]=qup+1;
--qup;
count+=opcost[norr]+opcost[nott];
flag=false;
}
if(flag && dir==downn)
{
int[] Y=NANDD(Sdown,X), Z=NOTT(Y);
if(flagg) {W[W.length]=copy(X); count+=X[cost];}
W[W.length]=copy(Y);
W[W.length-1][name]=outnott; W[W.length-1][anmbr]=qdown+1;
W[W.length]=copy(Z); Sdown=copy(Z);
W[W.length-1][name]=outt; W[W.length-1][anmbr]=qdown+1;
++qdown;
count+=opcost[nandd]+opcost[nott];
flag=false;
}
}
int S=W.length;
for(int k=0;k<S && flag;++k)
{
if(qdown<chainlength)
{
int[] A=W[k];
int[] T=ANDD(Sdown,A);
if(flag && summ(T)==a[qdown]) {APPEND(A,downn,false);}
}
if(qup>=0)
{
int[] A=W[k];
int[] T=ORR(Sup,A);
if(flag && summ(T)==a[qup]) {APPEND(A,upp,false);}
}
}
int HLENOLD=H.length;
for(int k=WLENOLD;k<S;++k)
{
int[] A=NOTT(W[k]);
for(int[] X : new int[][]{A})
if(NEW(X,H))
H[H.length]=copy(X);
}
for(int k=WLENOLD;k<S;++k)
for(int m=0;m<S;++m)
{
int[] A=ANDD(W[k],W[m]), B=ORR(W[k],W[m]), C=NANDD(W[k],W[m]), D=NORR(W[k],W[m]), E=NADJ(W[k],W[m]), F=NADJ(W[m],W[k]);
for(int[] X: new int[][]{C,D,E,F})//,A,B})
if(NEW(X,H))
H[H.length]=copy(X);
}
int SS=H.length;
for(int m=0;m<SS && H.length<MAXHEAPSIZE;++m)
for(int k=WLENOLD;k<S;++k)
{
int[] A=NADJ(H[m],W[k]);
for(int[] X: new int[][]{A})//,A,B})
if(NEW(X,H))
H[H.length]=copy(X);
}
H=purge(H,W, HLENOLD);
H=sort(H,LESS);
if(verbose) write(REPORT(H));
SS=H.length;
WLENOLD=W.length;
if(qq==chainlength-2 && verbose) write("H grew to length "+string(H.length));
T INTCOST;
if(flag) INTCOST=CHECKINTCOST(qup,qdown,a,W,H);
if(flag && verbose)
{
string s=""; for(int k=0;k<inputs;++k) s+=string(LSTORD[INTCOST.ord][k])+" ";
write("Cost of interval build = "+string(INTCOST.cost) + " with order "+s+ " length "+string(INTCOST.length));
}
for(int k=0;k<SS && flag;++k)
{
int[] A=copy(H[k]);
if(qdown<chainlength)
{
int[] T=ANDD(Sdown,A);
if(flag && summ(T)==a[qdown] && A[cost]+opcost[andd]<=INTCOST.cost)
{
APPEND(A,downn);
}
}
if(qup>=0)
{
int[] T=ORR(Sup,A); if(flag && summ(T)==a[qup] && A[cost]+opcost[andd]<=INTCOST.cost)
{
APPEND(A,upp);
}
}
}
for(int m=0;m<SS && flag;++m)
{
int[] A=NOTT(H[m]);
if(qdown<chainlength)
{
if(flag && summ(ANDD(Sdown,A))==a[qdown] && H[m][cost]+A[cost]+opcost[andd]<=INTCOST.cost)
{
count+=H[m][cost];
W[W.length]=copy(H[m]); APPEND(A,downn);}
}
if(qup>=0)
{
if(flag && summ(ORR(Sup,A))==a[qup] && H[m][cost]+A[cost]+opcost[andd]<=INTCOST.cost)
{
count+=H[m][cost];
W[W.length]=copy(H[m]); APPEND(A,upp);}
}
}
for(int m=0;m<SS && flag;++m)
for(int k=0;k<S && flag;++k)
{
int[] E=NADJ(H[m],W[k]), F=NOTT(E);
int[][] XX= new int[][]{E,F};//A,B};
int[] wm={1,1};
for(int k=0;k<XX.length;++k)
{
int[] X=XX[k];
if(qdown<chainlength)
{
if(flag && summ(ANDD(Sdown,X))==a[qdown] && X[cost]+wm[k]H[m][cost]+opcost[andd]<INTCOST.cost)
{
if(k!=0) {count+=E[cost]; W[W.length]=copy(E);}
APPEND(X,downn);
if(k==0) ++GATE3COUNT;
}
}
if(qup>=0)
{
if(flag && summ(ORR(Sup,X))==a[qup] && X[cost]+wm[k]H[m][cost]+opcost[andd]<INTCOST.cost)
{
if(k!=0) {count+=E[cost]; W[W.length]=copy(E);}
APPEND(X,upp);
if(k==0) ++GATE3COUNT;
}
}
}
}
for(int m=0;m<SS && flag;++m)
for(int k=0;k<S && flag;++k)
{
int[] A=ANDD(W[k],H[m]), B=ORR(W[k],H[m]), C=NANDD(W[k],H[m]), D=NORR(W[k],H[m]), E=NADJ(H[m],W[k]);
int[][] XX= new int[][]{E,C,D};//A,B};
int[] wm={0,1,1};
for(int k=0;k<XX.length;++k)
{
int[] X=XX[k];
if(qdown<chainlength)
{
if(flag && summ(ANDD(Sdown,X))==a[qdown] && X[cost]+wm[k]H[m][cost]+opcost[andd]<=INTCOST.cost)
{
if(k!=0) {count+=H[m][cost]; W[W.length]=copy(H[m]);}
APPEND(X,downn);
if(k==0) ++GATE3COUNT;
}
}
if(qup>=0)
{
if(flag && summ(ORR(Sup,X))==a[qup] && X[cost]+wm[k]H[m][cost]+opcost[andd]<=INTCOST.cost)
{
if(k!=0) {count+=H[m][cost]; W[W.length]=copy(H[m]);}
APPEND(X,upp);
if(k==0) ++GATE3COUNT;
}
}
}
}
if(verbose && flag) {write("working slowly SS="+string(SS));}
if(flag)
{
for(int k=0;k<SS && flag;++k)
{
if(k%20==0 && verbose) write(k);
for(int m=0;m<k && flag;++m)
{
int[] A=NANDD(H[k],H[m]), B=NORR(H[k],H[m]), C=ANDD(H[k],H[m]), D=ORR(H[k],H[m]), E=NADJ(H[m],H[k]), F=NADJ(H[k],H[m]);
int[] wm=new int[]{0,1,1,1}, wk=new int[]{1,0,1,1};
int[][] XX=new int[][]{E,F,A,B};
for(int kk=0;kk<XX.length;++kk)
{
int[] X=XX[kk];
if(qdown<chainlength)
{
if(flag && summ(ANDD(Sdown,X))==a[qdown] && opcost[andd]+X[cost]+H[m][cost]wm[kk]+H[k][cost]wk[kk]<=INTCOST.cost)
{
count+=H[m][cost]wm[kk]+H[k][cost]wk[kk];
if(wk[kk]>0) W[W.length]=copy(H[k]); if(wm[kk]>0) W[W.length]=copy(H[m]);
APPEND(X,downn);}
}
if(qup>=0)
{
if(flag && summ(ORR(Sup,X))==a[qup] && opcost[andd]+X[cost]+H[m][cost]wm[kk]+H[k][cost]wk[kk]<=INTCOST.cost)
{
count+=H[m][cost]wm[kk]+H[k][cost]wk[kk];
if(wk[kk]>0) W[W.length]=copy(H[k]); if(wm[kk]>0) W[W.length]=copy(H[m]);
APPEND(X,upp);}
}
}
}
}
}
if(flag)
{
INTCOST=CHECKINTCOST(qup,qdown,a,W,H,true);
if(flag && verbose) write("Cost of interval build revised to "+string(INTCOST.cost));
int ord=INTCOST.ord;
if(verbose) write("INTERVAL AT CHOICE "+string(chainlength-qq)+" WITH ord="+string(ord)+" W="+string(W.length)+" H="+string(H.length) );
int beg=count;
int aa=INTCOST.start, maxlength=INTCOST.length;
int qq1;
int[][] WA;
if(INTCOST.dirr=="down") qq1=qdown; else qq1=qup;
if(qq1==qdown)
{
WA=copy(NLST(aa,ord,W,H,true,maxlength));
for(int k=WA.length-2;k>0 && flag;--k)
{
W[W.length]=copy(WA[k]);
count+=WA[k][cost];
}
}
if(qq1==qup)
{
WA=copy(NLST(aa,ord,W,H,true,maxlength));
for(int k=WA.length-2;k>0;--k)
{
W[W.length]=copy(WA[k]);
count+=WA[k][cost];
}
}
{
if(qq1==qdown)
{
APPEND(WA[0],downn);
}
if(qq1==qup)
{
APPEND(WA[0],upp);
}
}
if(verbose) write("added "+string(count-beg)+" to get "+string(count));
}
if(verbose)
{
write("done with choice "+string(chainlength-qq)+" with count="+string(count)+" W="+string(W.length)+" H="+string(H.length)
+" we have "+(qupold>=0?string(summ(Sup))+"="+string(a[qupold]):"")+" or "
+(qdownold<chainlength?string(summ(Sdown))+"="+string(a[qdownold]):""));
//pause();
}
if(count+qq>=ccount) {qq=-1; count=10000;}
}
if(count<ccount){ccount=count; Wopt=copy(W);}
if(verbose) {disp(comb(W));}
write(ccount,count,H.length);
bool flag3=false;
for(int k=0;k<W.length;++k) if(EXTRAARGNUM(W[k])>0) flag3=true;
//if(flag3) {disp(comb(W));}
}
++NN; ++ss[ccount];
write("summary");
write(ccount, NN);
COUNT=max(COUNT,ccount);
if(rawcircuit) {write("Raw circuit"); write(""); print(comb(Wopt)[0*inputs:Wopt.length]); write("");}
if(circuit) {write("Circuit"); write(""); disp(comb(Wopt)); write("");}
//pause();
int[] aact=AA(comb(Wopt),ccount);
for(int k=0;k<chainlength;++k) if(aact[k]!=a[k]) {write("Failure!"); write(aact); pause();}
if(statistics)
{
write("");
write("Statistics for "+string(NN)+" runs:");
write("");
write("3 input gates were used "+string(GATE3COUNT)+" times; CHECKINCOST failed "+string(FAILCOUNT)+" times");
write("");
int[] NUM; for(int k=0; k<200;++k) NUM[k]=k;
int u=0; while(ss[u]==0) ++u;
write( NUM[u:COUNT+1], ss[u:COUNT+1]);
write("");
}
write("");
write("*************************");
write("");
}
pause();