#include <stdio.h>
#include "datamat.h"
#include "block.h"
#include "valcnt.h"
#include "logical.h"

static char *compblkid = "$Id: compblk.c,v 1.2 1996/12/30 23:01:31 galway Exp galway $";

/*****************************************************************/
/*  


    compblk.c

    Copyright (C) 2004  Lionel A. Galway

    This program 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 2 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.

    For a copy of the GNU General Public License write to the Free Software
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA


 
    This is the workhorse of the Hartigan algorithm.  This constructs
    a block by finding the best row as the nucleus, then
    adding/deleting rows and columns according to their agreement with
    the block symbols.

    L. Galway 30-DEC-1996
/*****************************************************************/

extern struct valcnt *col_freq();
extern int row_max();
struct block *init_block();
extern void comp_blkcd();
extern int row_score();
extern int col_score();
extern void add_row();
extern void del_row();
extern void add_col();
extern void del_col();
extern void setblkind();
extern int block_count();
extern void free_valcnt();

extern struct valcnt *col_freq();

struct block *compblk(d,iblk)
struct datamat *d;int iblk;
{
  struct block *retval;
  int NR,NC,i,irow,blkcnt,j,rmax,rscor;
  struct valcnt **cvals; enum logical chge;

  int k;struct valcnt *tmpv;

  /*  Find the starting row by finding the row with the maximum sum of
      frequencies for the values in the row which are not block
      symbols. */
  cvals = (struct valcnt **)malloc(d->ncols * sizeof(struct valcnt));
  for (i=0;i<d->ncols;i++) cvals[i]=col_freq(d,i,NULL);
  print_valcnts(cvals,d->ncols,d->collabs);
  rmax = row_max(d,cvals);free_valcnt(cvals);
  retval=init_block(d,rmax,iblk);
  print_block(retval,d);

  /*  Add or delete rows/columns depending on whether their scores are
      > 0.  Note that need to test if row/column already in block.
      Stop when there has been no change in a cycle. */
  chge = TRUE;
  while (chge == TRUE) {
    chge = FALSE;
    /* Search rows */
    for (i=0;i<d->nrows;i++) {
      rscor=row_score(d,retval,i);
      printf("compbplk: row=%2d(%s) score=%3d",i,d->rowlabs[i],rscor);
      if (retval->irow[i] ==0 && rscor > 0) {
	add_row(i,retval);chge=TRUE;printf(" a\n");/*debug*/
      } else if (retval->irow[i] ==1 && rscor <= 0 ) {
	del_row(i,retval);chge=TRUE; printf(" d\n");/*debug*/
      } else {printf("\n");};  /*debug*/
    };
    /* Search columns */
      /*debug*/
    for (k=0;k<d->ncols;k++) {
	printf ("col=%d ",k);
	tmpv = col_freq(d,k,retval); print_valcnt(tmpv,d->collabs[k]);
	free_valcnt(tmpv);
    };
      /*debug*/
    for (i=0;i<d->ncols;i++) {
      rscor = col_score(d,i,retval);
      printf("compbplk: col=%d(%s) score=%d",i,d->collabs[i],rscor);
      if (retval->icol[i]==0 && rscor > 0) {
	add_col(i,retval);chge=TRUE;printf(" a\n"); /*debug*/
      } else if (retval->icol[i]==1 && rscor <= 0) {
	del_col(i,retval);chge=TRUE;printf(" d\n"); /*debug*/
      } else {printf("\n");}; /*debug*/
    };

    /* Compute a new block code */
    for (k=0;k<d->ncols;k++) {
      if (retval->icol[k]==1) {
	printf ("col=%d ",k);
	tmpv = col_freq(d,k,retval); print_valcnt(tmpv,d->collabs[k]);
	free_valcnt(tmpv);
      };
    };
    comp_blkcd(d,retval);
    print_block(retval,d);
  };

  /* After block is fixed, set the block symbol indicators... */
  setblkind(d,retval);
  /* ... and compute the block count */
  retval->blkcnt = block_count(retval,d);

  print_block(retval,d);
  return(retval);
}
