/*
 Copyright (C) Andrew Wuensche
 
 This file is part of DDLab (Discrete Dynamics Lab) <www.ddlab.org>
 
 DDLab is free software: you can redistribute it and/or modify
 it under the terms of the GNU General Public License as published by
 the Free Software Foundation, either version 3 of the License, or
 (at your option) any later version.
 
 This program is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 GNU General Public License for more details.
 
 You should have received a copy of the GNU General Public License
 along with DDLab.  If not, see <http://www.gnu.org/licenses/>.
 */

/******* learn/forget - (revised for multi-value Jan 2003) *******/

#include "edecfunc.h"

/***************  list of functions in this file ************/
/*void sculpt_basin_field(void)*/
/*void shuffle_order(signed int* array, signed int size)*/
void review_asp_pre_images(unsigned int startyb,
     char par, char hamming,
	 signed long startdec,signed long enddec,
		  signed int prestep, char pre_range);


/************************* learning, April 94 *************************/
char sculpt_basin_field(char highlight_only){

  char learn,learn_sometime=0,scul,
       **norepre,**okrepre,*temp,
       maxdecL,pre_range,prestep,
       wr_status,
       hamming,
       par, temp_just_G;

  char temp_showbits_1d_as_2d, temp_shownumbers,
       forwards_only=0;

  signed int  *pnhood,*shuff_wire,*shuff_z,*shuff_z2,
       *shuff_norepre,*shuff_okrepre,
       u,u1,
       startx,starty,leftx,newno,z,zz,zzz,
       lrn,n,sn,rsn,i,wire,
       ok,no,
       index1,index2,
       tempx,tempy,
       sum1s;
  unsigned int zu,parsize,startyb;
  unsigned long maxstate,startdec,enddec,zdec,state_dec_max;

  /*to preserve node presentation set in drparax.c*/
  temp_showbits_1d_as_2d=showbits_1d_as_2d;
  temp_shownumbers=shownumbers;

  temp_just_G=just_G;
  state_dec_max=0;
  state_dec_max=max_dec_rule(lineL-1,value_range);
  /*check top of seed window*/  
  startyb=select_seed(1,tar,"target state",1);
  
  compress_1d_local=0;
  dont_save=1;
  /*memory for pseudo-nhood*/
  if ((pnhood=(signed int *)calloc(nhood,sizeof(signed int)))
			    ==NULL) outof_memory("pnhood");
  /*to shuffle wiring*/
  if ((shuff_wire=(signed int*)calloc(nhood,sizeof(signed int)))
			    ==NULL) outof_memory("shuff_wire");
  if ((shuff_z=(signed int*)calloc(lineL,sizeof(signed int)))
			    ==NULL) outof_memory("shuffle_z");
  if ((shuff_z2=(signed int*)calloc(lineL,sizeof(signed int)))
			    ==NULL) outof_memory("shuff_z2");
  startx=getx;
  starty=gety;
  leftx=xtext*CWidth;
  regular2d=0;/*may be rewired*/
  if      (nonlocal==0 && rulemix==0)	wr_status=0;
  else if (nonlocal==0 && rulemix)	wr_status=1;
  else if (nonlocal && rulemix==0)	wr_status=2;
  else if (nonlocal && rulemix)	wr_status=3;

  /*realy intended for basins, but learning also works for space-time patterns*/
  if (direction=='f' && limitcheck==0) forwards_only=1;
 start:
  moveto(leftx-3,startyb-vgay(15));
  if (forwards_only==1) 
             sprintf(textb[0],"learn/forget: set target state");
  else{
     if (highlight_only==1) sprintf(textb[0],"highlight only: set target state");
     else sprintf(textb[0],"learn/forget/highlight: set target state");
  }
  draw_box(13,getx,gety,getx+Maxx*.6,gety+vgay(15),1,0);
  outtext(textb[0]);
  moveto(leftx,vgay(315));
  select_seed(0,tar,"target state",1);
  if (is[0]=='q') goto skip_learn;

 start1:
  /*sprintf(textb[4],"");*/
  moveto(leftx-3,startyb-vgay(15));
  draw_box(-1,getx,gety,getx+Maxx*.6,gety+vgay(15),1,0);
  /*moveto(leftx,gety);*/
  sprintf(textb[0],"pre-images: ");
  if (value_range==2) sprintf(textb[1],
       "as before-b parity-p range-r Hamm-h1/h2 list-(def 1):");
  else sprintf(textb[1],
       "as before-b range-r Hamm-h1 list-(def 1):");
  outtext(textb[0]);
  outtext(textb[1]);
  input_string(4,0);
  if (is[0]=='q'){
     freeimage(boximage[13]);
     memory_box(1,NULL);
     goto start;
  }
  if (is[0]=='b'){
     newno=notolearn;
     if (newno==0) newno=1;
     goto skip_pre; /*same pre-images as before*/
  }
  if (is[0]==13||is[0]=='r'||is[0]=='h'||atoi(is)<=0) newno=1;
  else newno=atoi(is);
  pre_range=0;
  if (is[0]=='r') pre_range='r';
  else if (is[0]=='h'){
     hamming=1;
     pre_range='h';
     if (is[1]=='2' && value_range==2) hamming=2;
  }
  else if (is[0]=='p' && value_range==2) pre_range='p';
  if (pre_range=='p'){
     moveto(leftx-3,startyb-vgay(15));
     draw_box(-1,getx,gety,getx+Maxx*.6,gety+vgay(15),1,0);
     moveto(leftx,gety);
     outtext("parity: odd-1, even-(def):");
     input_string(1,1);
     if (is[0]=='q') goto start1;
     else if (is[0]=='1') par=1;
     else par=2;

     moveto(leftx-3,startyb-vgay(15));
     draw_box(-1,getx,gety,getx+Maxx*.6,gety+vgay(15),1,0);
     moveto(leftx,gety);

     if (lineL>20) parsize=20;
     else parsize=lineL;
     sprintf(textb[0],"enter part system size (def %d):",parsize);
     outtext(textb[0]);
     /*input_string(strlen(itoa(lineL,textb[2],10)),1);*/
     sprintf(textb[2],"%d",lineL);
     input_string(strlen(textb[2]),1);
     if (is[0]=='q') goto start1;
     parsize=atoi(is);
     if (is[0]==13 || (signed int)parsize==0 || parsize>lineL) parsize=lineL;
     if (parsize>20) parsize=20;
     /*half have odd/even parity*/
     newno=(signed int) (pow(2,(double)(parsize)))/2;
  }
  if (pre_range=='r'){
     if (lineL>maxL_lu) maxdecL=maxL_lu;
     else maxdecL=lineL;
     maxstate=(unsigned long) (pow(value_range,(double)(maxdecL))-1);

     moveto(leftx-3,startyb-vgay(15));
     draw_box(-1,getx,gety,getx+Maxx*.6,gety+vgay(15),1,0);
     moveto(leftx,gety);
     sprintf(textb[0],
	   "range of pre-images (def 1-10), max %lu), start:",maxstate);
     outtext(textb[0]);
     /*input_string(strlen(ultoa(maxstate,textb[2],10)),1);*/
     sprintf(textb[2],"%lu",maxstate);
     input_string(strlen(textb[2]),1);
     if (is[0]=='q') goto start1;
     startdec=atolu(is);
     if (is[0]==13 || startdec==Maxlu 
            || startdec==Maxlu+1 || startdec>maxstate) startdec=1;
     outtext(" end:");
     /*input_string(strlen(ultoa(maxstate,textb[2],10)),1);*/
     sprintf(textb[2],"%lu",maxstate);
     input_string(strlen(textb[2]),1);
     if (is[0]=='q') goto start1;
     enddec=atolu(is);
     if (is[0]==13 || enddec<startdec) enddec=startdec+9;
     if (enddec>maxstate) enddec=maxstate;
     outtext(" step:");
     input_string(3,1);
     if (is[0]=='q') goto start1;
     prestep=atoi(is);
     if (is[0]==13 || prestep<=0 || 
                  prestep>(enddec-startdec+1)/2) prestep=1;
     if (prestep==1) newno=
                     floor(((float)(enddec-startdec+1))/prestep);
     else newno=floor(((float)(enddec-startdec))/prestep +1);
  }
  if (pre_range=='h'){
        newno=lineL*(value_range-1); /*1-bit/value from target*/
        if (hamming==2) newno=lineL*lineL; /*2-bits/values from target*/
  }

  for (z=0;z<=notolearn-1;z++) free(learn_pre[z]);
  free(learn_pre);
  sprintf(textb[0],"learn_pre");
  if ((learn_pre=(char**)calloc(newno,sizeof(char*)))
			      ==NULL) outof_memory(textb[0]);
  for (z=0;z<=newno-1;z++){
	sprintf(textb[0],"learn_pre[%d]",z);
	if ((learn_pre[z]=(char *)calloc(bytesL,sizeof(char)))
			      ==NULL) outof_memory(textb[0]);
  }

 skip_pre:

  memory_box(1,NULL);
  notolearn=newno;
  if (pre_range=='h' && value_range==2){
     index2=-1;
     for (zu=0;zu<=L;zu++){
	index1=zu;
	if (hamming==2) index1=index2+1;
	memmove(learn_pre[index1],tar,bytesL);
        set_bit(learn_pre[index1],zu,abs(get_bit(learn_pre[index1],zu)-1));
        
	if (hamming==2){
	   index2=index1;
	   for (zz=0;zz<=L-1;zz++){
	      index2+=1;
	      memmove(learn_pre[index2],learn_pre[index1],bytesL);
	         set_bit(learn_pre[index2],zz,
				abs(get_bit(learn_pre[index2],zz)-1));
	      for (zzz=0;zzz<=index2-1;zzz++){
		 if (memcmp(learn_pre[index2],learn_pre[zzz],
					       bytesL)==0) index2-=1;
	      }
	   }
	}
     }
     if (hamming==2){
	for (z=index2+1;z<=notolearn-1;z++) free(learn_pre[z]);
	notolearn=index2+1;
     }
  }

  else if (pre_range=='h' && value_range>=3){
    char zv;
     index1=-1;
     for (zv=0; zv<=value_range-1; zv++){
        for (zu=0;zu<=L;zu++){	   
           if (get_value(tar,zu)!=zv){
              index1++;
              memmove(learn_pre[index1],tar,bytesL);
              set_value(learn_pre[index1],zu,zv);
              /*fprintf(stderr," %d",index1);*/
           }
        }        
     }
     notolearn=index1+1;
  }

  else if (pre_range=='p' && value_range==2){
     sprintf(textb[0],"temp");
     if ((temp=(char *)calloc(bytesL,sizeof(char)))
				    ==NULL) outof_memory(textb[0]);
     maxstate=pow(2,(double)(parsize));
     zdec=-1;
     for (z=maxstate-1;z>=0;z--){
	sum1s=0;
	if (value_range==2) dec_to_bit_line(temp,z,lineL);
        else dec_to_value_line(temp,z,lineL);
	for (zz=lineL-1;zz>=0;zz--){
	   if (value_range==2){ 
              if (get_bit(temp,zz)==1) sum1s++;
           }
           else sum1s+= get_value(temp,zz);
	}
	if (sum1s%2==0 && par==2){  /*even parity*/
	   zdec++;
	   memmove(learn_pre[zdec],temp,bytesL);
	}
	else if (sum1s%2==1 && par==1){  /*odd parity*/
	   zdec++;
	   memmove(learn_pre[zdec],temp,bytesL);
	}
     }
     free(temp);
  }
  else if (pre_range=='r'){
     zdec=startdec;
     for (z=0;z<=notolearn-1;z++){
	if (value_range==2) dec_to_bit_line(learn_pre[z],zdec,lineL);
        else dec_to_value_line(learn_pre[z],zdec,lineL);
	zdec+=prestep;
     }
  }
  else if (pre_range==0){
     for (z=0;z<=notolearn-1;z++){
	moveto(leftx,vgay(315));
	sprintf(textb[3],"aspiring pre-image %d",z+1);
	select_seed(0,learn_pre[z],textb[3],1);
	memory_box(1,NULL);
	if (is[0]=='q') goto start1;
     }
  }
  /*preview target - pre-images, list in decimal if within limits*/
  /*if (lineL<=32)*/ 
  review_asp_pre_images(startyb,par,hamming,
			  startdec,enddec,prestep,pre_range);

  if (is[0]=='q') goto start1;

  moveto(leftx-3,startyb-vgay(15));
  draw_box(-1,getx,gety,getx+Maxx*.6,gety+vgay(15),1,0);
  moveto(leftx,gety);
 
  if (highlight_only==1){ /*for 1d CA -- dont't convert to nonlocal*/
     if (forwards_only==0){
        sprintf(textb[0]," highlight only-(def):");
        outtext(textb[0]);
        input_string(1,0);
        dontcompress=1;
     }
     goto end;
  }
  else{
     if (wr_status<=1){
        if (wr_status==0) 
                  sprintf(textb[0],"local 1d CA: nonlocal wiring-w: ");
        else if (wr_status==1) 
                  sprintf(textb[0],"local 1d, rule-mix: nonlocal wiring-w: ");
        outtext(textb[0]);
        input_string(1,0);
        if (is[0]=='w'){        
           nonlocal=1;
	   regular3d=regular2d=
               compress_1d_local=dontcompress=0;
           if (nonlocal && rulemix==0) wr_status=2;
           else if (nonlocal && rulemix) wr_status=3;
           outtext(" ");
        } 
        else{
	   if (forwards_only==0){
              sprintf(textb[0]," highlight only-(def):");
              outtext(textb[0]);
              input_string(1,0);
           }
           goto end;
        }
     }
     if (wr_status>=2){
        if (forwards_only==1) sprintf(textb[0],"forget-f, learn-(def):");
	else sprintf(textb[0],"highlight only-h, forget-f, learn-(def):");
        outtext(textb[0]);
        input_string(1,0);  
        if (is[0]=='q') goto start1;
        else if (is[0]=='f') learn='f';
        else if (is[0]=='h' && forwards_only==0){
           learn='h';
           goto end;
        }
        else learn='l';
        learn_sometime=1;
     }
  }
  moveto(leftx-3,startyb-vgay(15));
  draw_box(-1,getx,gety,getx+Maxx*.6,gety+vgay(15),1,0);
  moveto(leftx,gety);
  if (wr_status==1) sprintf(textb[1],"bit-flips only-(def):");
  else if (wr_status==2) sprintf(textb[1],"wire-moves only-(def):");/*now redundant*/
  else if (wr_status==3){
      if (value_range==2) sprintf(textb[1], "wire-moves -w, bit-flips-(def):");
      else sprintf(textb[1], "wire-moves -w, value-flips-(def):");
  }
  if (learn=='f') sprintf(textb[0],"forget by %s",textb[1]);
  else if (learn=='l') sprintf(textb[0],"learn by %s",textb[1]);
  outtext(textb[0]);
  input_string(1,0);
  if (is[0]=='q') goto start1;
  else if (is[0]=='w') scul='w'; /*scul=sculpt*/
  else scul='b';
  if (wr_status==1) scul='b';
  if (wr_status==2) scul='w';
 startlearning:
  for (lrn=0;lrn<=notolearn-1;lrn++){
    shuffle_order(shuff_z2,lineL);/*shuffle cell order*/
    for (n=L; n>=0; n--){
      sn=shuff_z2[n];
      if (rulemix==0) rsn=0;/*to fix bug, single rule*/
      else rsn=sn;
      for (i=0;i<=nhoodm[n]-1;i++) pnhood[i]=wiring[sn][i];
      u=0; /*find dec value of actual or pseudo-nhood*/
      for (i=nhoodm[n]-1;i>=0;i--){
	  if (value_range==2) u+=get_bit(learn_pre[lrn],
                   pnhood[i])*(signed int)pow(2,(double)i);
          else u+=get_value(learn_pre[lrn],
                   pnhood[i])*(signed int)pow(value_range,(double)i);
      }
      if (get_value(carule[rsn],u)!=get_value(tar,sn)){
	  if (learn=='f') break; /*already forgotten*/
      }
      else if (learn=='l') continue;
      if (scul=='b'){
	 if (value_range==2){ 
            set_bit(carule[rsn],u,abs(get_bit(carule[rsn],u)-1));
         }
         else set_value(carule[rsn],u,get_value(tar,sn));
	 if (learn=='f') break;
      }
      if (scul=='w'){
	 /*shuffle wire order of psuedo nhood*/
	 shuffle_order(shuff_wire,nhoodm[n]);
	  /*try a wire move in shuffled order*/
	  for (wire=0;wire<=nhoodm[n]-1;wire++){
	    shuffle_order(shuff_z,lineL);/*shuffle cell order for coupling*/
	    /*try coupling at each poss*/
	    for (z=0;z<=lineL-1;z++){
	       /*try different wire coupling*/
	       pnhood[shuff_wire[wire]]=shuff_z[z];
	       for (zz=0;zz<=lrn;zz++){ /*no of pre-images to learn*/
		  u1=0;
		  for (i=nhoodm[n]-1;i>=0;i--){
		     if (value_range==2) u1+=get_bit(learn_pre[zz],
			    pnhood[i])*(signed int)pow(2,(double)i);
                     else  u1+=get_value(learn_pre[zz],
			    pnhood[i])*(signed int)pow(value_range,(double)i);
                  }
		  /*test ouput (and all pervious)*/
		  if (get_value(carule[rsn],u1)!=get_value(tar,sn)){
		     if (learn=='l') goto nextposs;
		  }
		  else if (learn=='f') goto nextposs;
	       }
	       /*if no missmatch (or match-forget) found, accept re-wiring*/
	       wiring[sn][shuff_wire[wire]]=shuff_z[z];
	       goto nextcell;
	       nextposs:;
	    }
	  }
      }
      nextcell:;
      if (learn=='f') break;
    }
  }
  if (scul=='w'){
     sprintf(textb[0],"norepre");
     if ((norepre=(char**)calloc(notolearn,sizeof(char*)))
				       ==NULL) outof_memory(textb[0]);
     sprintf(textb[0],"okrepre");
     if ((okrepre=(char**)calloc(notolearn,sizeof(char*)))
				       ==NULL) outof_memory(textb[0]);
     for (z=0;z<=notolearn-1;z++){
	sprintf(textb[0],"norepre[%d]",z);
	if ((norepre[z]=(char *)calloc(bytesL,sizeof(char)))
				       ==NULL) outof_memory(textb[0]);
	sprintf(textb[0],"okrepre[%d]",z);
	if ((okrepre[z]=(char *)calloc(bytesL,sizeof(char)))
				       ==NULL) outof_memory(textb[0]);
     }
     memory_box(1,NULL);
     /*identify pre-images not learnt by rewiring*/
     no=-1;
     ok=-1;
     for (z=0;z<=notolearn-1;z++){
	for (n=L; n>=0; n--){
           if (rulemix==0) rsn=0;/*to fix bug, single rule*/
           else rsn=n;
	   for (i=0;i<=nhoodm[n]-1;i++) pnhood[i]=wiring[n][i];
	   u=0; /*find dec value of actual or pseudo-nhood*/
	   for (i=nhoodm[n]-1;i>=0;i--){
	      if (value_range==2) u+=get_bit(learn_pre[z],
		   pnhood[i])*(signed int)pow(2,(double)i);
              else u+=get_value(learn_pre[z],
                   pnhood[i])*(signed int)pow(value_range,(double)i);
           }
	   if (get_value(carule[rsn],u)!=get_value(tar,n)) goto notlearnt;
	}
	ok+=1;
	memmove(okrepre[ok],learn_pre[z],bytesL); /*learnt pre-images*/
	goto waslearnt;
       notlearnt:
	no+=1;
	memmove(norepre[no],learn_pre[z],bytesL); /*not learnt*/
       waslearnt:;
     }
     moveto(leftx,vgay(315));
     tempx=getx;
     tempy=gety;
     draw_box(14,tempx-3,tempy,Maxx-vgax(70),Maxy-vgay(50),1,0);
     moveto(leftx,gety);
     if (state_dec_max>0) sprintf(textb[0],"target state=%lu,",dec_equiv(tar,L));
     else sprintf(textb[0],"target (n=%d)",lineL);
        outtext(textb[0]);
     if (no>-1){
        moveto(leftx,gety+CHeight);
	for (z=0;z<=no;z++){
	   if (lineL<=maxL_lu) sprintf(textb[0],"%lu,",dec_equiv(norepre[z],L));
	   else sprintf(textb[0],"x ");
           if (getx>Maxx-vgax(70)-textwidth("   <-no")-vgax(3))
			      moveto(leftx,gety+CHeight);
	   outtext(textb[0]);
	}
	outtext("<-no");
     }
     if (ok>-1){
	moveto(leftx,gety+CHeight);
	for (z=0;z<=ok;z++){
	   if (lineL<=maxL_lu) sprintf(textb[0],"%lu,",dec_equiv(okrepre[z],L));
           else sprintf(textb[0],"x ");
	   if (getx>Maxx-vgax(70)-textwidth("   <-ok")-vgax(3))
			      moveto(leftx,gety+CHeight);
	   outtext(textb[0]);
	}
	outtext("<-ok");
     }
     /*all states successfully learnt or forgotten*/
     if ((no==-1 && learn=='l') || (ok==-1 && learn=='f')){
	for (z=0;z<=notolearn-1;z++){
	   free(norepre[z]);
	   free(okrepre[z]);
	}
	free(norepre);
	free(okrepre);
	memory_box(1,NULL);
	moveto(leftx,gety+CHeight);
	if (notolearn==1) outtext("success - aspiring pre-image");
	else outtext("success - all aspiring pre-images");
	if (learn=='l') outtext(" learnt");
	else if (learn=='f') outtext(" forgotten");
	moveto(leftx,gety+CHeight);
	outtext("cont-ret:");
	input_string(1,0);
     }
     else{
	if (learn=='l'){ /*LEARN*/
	   /*put last unlearnt at start*/
	   memmove(learn_pre[0],norepre[no],bytesL);
	   /*if any learnt*/
	   if (ok>-1){
	      /*if more than one were learnt, shuffle then copy*/
	      if (ok>0){
		 sprintf(textb[0],"shuffle_okrepre");
		 if ((shuff_okrepre=(signed int*)calloc (ok+1,sizeof(signed int)))
				     ==NULL) outof_memory(textb[0]);
		 shuffle_order(shuff_okrepre,ok+1);
		 for (z=ok;z>=0;z--) memmove(learn_pre[notolearn-1-no-z],
				      okrepre[shuff_okrepre[z]],bytesL);
		 free (shuff_okrepre);
	      }
	      else memmove(learn_pre[1],okrepre[0],bytesL); /*just one*/
	   }
	   if (no>1){  /*shuffle unlearnt (exept last), then copy*/
	      sprintf(textb[0],"shuffle_norepre");
	      if ((shuff_norepre=(signed int*)calloc (no,sizeof(signed int)))
				     ==NULL) outof_memory(textb[0]);
	      shuffle_order(shuff_norepre,no);
	      for (z=no-1;z>=0;z--) memmove(learn_pre[notolearn-1-z],
				   norepre[shuff_norepre[z]],bytesL);
	      free (shuff_norepre);
	   }
	   else memmove(learn_pre[notolearn-1],norepre[0],bytesL);
	}
	if (learn=='f'){ /*FORGET*/
	   /*put last not forgotten at start*/
	   memmove(learn_pre[0],okrepre[ok],bytesL);
	   /*if more than one were forgotten, shuffle then copy*/
	   if (no>0){
	      sprintf(textb[0],"shuffle_norepre");
	      if ((shuff_norepre=(signed int*)calloc (no+1,sizeof(signed int)))
					==NULL) outof_memory(textb[0]);
	      shuffle_order(shuff_norepre,no);
	      for (z=no;z>=0;z--) memmove(learn_pre[notolearn-1-ok-z],
				      norepre[shuff_norepre[z]],bytesL);
	      free (shuff_norepre);
	   }
	   else memmove(learn_pre[1],norepre[0],bytesL); /*just one*/

	   if (ok>1){  /*shuffle unforgotten (exept last), then copy*/
	      sprintf(textb[0],"shuffle_okrepre");
	      if ((shuff_okrepre=(signed int*)calloc (ok,sizeof(signed int)))
					==NULL) outof_memory(textb[0]);
	      shuffle_order(shuff_okrepre,ok);
	      for (z=ok-1;z>=0;z--) memmove(learn_pre[notolearn-1-z],
				   okrepre[shuff_okrepre[z]],bytesL);
	      free (shuff_okrepre);
	   }
	   else memmove(learn_pre[notolearn-1-z],okrepre[z],bytesL);
	}
	for (z=0;z<=notolearn-1;z++){
	   free(norepre[z]);
	   free(okrepre[z]);
	}
	free(norepre);
	free(okrepre);
	memory_box(1,NULL);
	moveto(leftx,gety+CHeight);
	if (wr_status==2) sprintf(textb[1],"wire-moves -w:");
	else if (wr_status==3){
            if (value_range==2) sprintf(textb[1], "wire-moves -w, bit-flips -b:");
            else sprintf(textb[1], "wire-moves -w, value-flips -b:");
        }
	if (learn=='f') sprintf(textb[0],"re-forget by %s",textb[1]);
	else if (learn=='l') sprintf(textb[0],"re-learn by %s",textb[1]);
	outtext(textb[0]);
	input_string(1,0);
	if (is[0]=='w' || is[0]=='b'){
	   if (is[0]=='b' && wr_status==3) scul='b';
           sprintf(textb[9],"%s","boximage[14]");
	   putimage(tempx-3,tempy,boximage[14],COPY_PUT,textb[9]);
	   freeimage(boximage[14]);
	   goto startlearning;
	}
     }
     sprintf(textb[9],"%s","boximage[14]");
     putimage(tempx-3,tempy,boximage[14],COPY_PUT,textb[9]);
     freeimage(boximage[14]);
  }
  moveto(leftx-3,startyb-vgay(15));
  draw_box(-1,getx,gety,getx+Maxx*.6,gety+vgay(15),1,0);
  moveto(leftx,gety);
  if (forwards_only==1) outtext("learn/forget more-m:");
  else outtext("learn/forget/highlight more-m:");
  input_string(1,0);
  if (is[0]=='m'){
	moveto(leftx-3,startyb-vgay(15));
        sprintf(textb[9],"%s","boximage[13]");
	putimage(getx,gety,boximage[13],COPY_PUT,textb[9]);
	freeimage(boximage[13]);
	memory_box(1,NULL);
	goto start;
  }
 end:

  if (forwards_only==0){
     hilight_learn=1;
     moveto(leftx-3,startyb-vgay(15));
     draw_box(-1,getx,gety,getx+Maxx*.6,gety+vgay(15),1,0);
     sprintf(textb[0],"highlight: none-n, suppess all other nodes-s:");
     outtext(textb[0]);
     input_string(1,0);
     if (is[0]=='n') hilight_learn=0;
     if (is[0]=='s') hilight_learn=2;
  }

 skip_learn:
  moveto(leftx-3,startyb-vgay(15));
  sprintf(textb[9],"%s","boximage[13]");
  putimage(getx,gety,boximage[13],COPY_PUT,textb[9]);
  freeimage(boximage[13]);
  free(pnhood);
  free(shuff_wire);
  free(shuff_z);
  free(shuff_z2);
  memory_box(1,NULL);
  moveto(startx,starty);
  dont_save=0;
  just_G=temp_just_G;
  /*to preserve node presentation set in drparax.c*/
  showbits_1d_as_2d=temp_showbits_1d_as_2d;
  shownumbers=temp_shownumbers;
  return(learn_sometime); /*=0 if network wasnt changed, 
			    ie. highlight only*/
}

/************************* shuffle the order ************************/
void shuffle_order(signed int* array, signed int size){
 signed int z,zz;

   for (z=0;z<=size-1;z++){
      redowire:
      array[z]= myrand()%(size);
      if (z>0){
	 for (zz=0;zz<=z-1;zz++){
	    if (array[z]==array[zz]) goto redowire;
	 }
      }
   }
}

/***** review target state and aspiring pre-images ***************/
void review_asp_pre_images(unsigned int startyb,
    char par, char hamming,
	 signed long startdec,signed long enddec,
		  signed int prestep, char pre_range){

  signed int leftx,tempx,tempy,tempy_cursor,tempx1,tempy1,z;
  char review_interupt;

     leftx=xtext*CWidth;
     moveto(leftx,vgay(315));
     tempx=getx;
     tempy=gety;
     draw_box(14,tempx-3,startyb,Maxx-vgax(70),Maxy-vgay(50),1,0);
     if (lineL<=maxL_lu)
            sprintf(textb[0],"target=%lu, pre-images=%d, ",
				  dec_equiv(tar,L),notolearn);
     else sprintf(textb[0],"target set, pre-images=%d, ",notolearn);
     outtext(textb[0]);
     if (pre_range=='p'){
	if (par==2) outtext("parity=even, ");
	else if (par==1) outtext("parity=odd, ");
	if (lineL<=maxL_lu) sprintf(textb[0],"max state=%lu, ",
			     dec_equiv(learn_pre[0],L));
        else sprintf(textb[0],"");
	outtext(textb[0]);
     }
     else if (pre_range=='h'){
        if (value_range==2){
	   if (hamming==1) sprintf(textb[0],"1 bit mutants, ");
	   else if (hamming==2) sprintf(textb[0],"1 & 2  bit mutants, ");
        }
        if (value_range>=3){
	   if (hamming==1) sprintf(textb[0],"1 value mutants, ");
	   else if (hamming==2) sprintf(textb[0],"1 & 2  value mutants, ");
        }
	outtext(textb[0]);
     }
     else if (pre_range=='r'){
	sprintf(textb[0],"range %lu-%lu, step=%d, ",
			       startdec,enddec,prestep);
	outtext(textb[0]);
     }

     outtext("cont-ret:");
     tempx1=getx;
     tempy_cursor=gety;
     moveto(leftx,gety+CHeight);
     tempy1=gety;

     review_interupt=0;
     /*if the state decimal equivalent is within limits,
       show aspiring preimages in decimal*/
     if (lineL<=maxL_lu){ 
        for (z=0;z<=notolearn-1;z++){
	   sprintf(textb[1],"%lu,",dec_equiv(learn_pre[z],L));        
	   if (getx>Maxx-vgax(70)-textwidth(textb[1]))
			       moveto(leftx,gety+CHeight);

	   if (gety>Maxy-vgay(50)-CHeight*2){
	      outtext("more-m cont-ret:");
	      input_string(1,0);
	      if (is[0]=='m'){
	         setfillstyle(SOLID_FILL,black);
	         bar(tempx-2,tempy1,Maxx-vgax(70)-1,Maxy-vgay(50)-1);
	         moveto(tempx,tempy1);
	      }
	      else{
	         review_interupt=1;
	         break;
	      }
	   }
	   outtext(textb[1]);
        }
     }
     if (review_interupt==0){
	moveto(tempx1,tempy_cursor);
	input_string(1,0);
     }
     sprintf(textb[9],"%s","boximage[14]");
     putimage(tempx-3,startyb,boximage[14],COPY_PUT,textb[9]);
     freeimage(boximage[14]);
}
/*---------------------------------------------------------------------*/



