/*
   File:        awdut.c
   Author:      Artur Dubrawski
   Created:     July 1999
   Description: AWD's general purpose utilities

   Copyright 1999, Schenley Park Research Inc
*/

#include "amut.h"
#include "dsut.h"



/*******************
Converts symbolic input attribute attnum to dyv so that
the resultant is supposedly monotonic w.r.t. the 'output' attribute already converted to dyv.
The 'output' dyv may reflect raw or ranked output data.
The input must be symbolic, and the input and the output must have the same
number of components.
The generated dyv may be seen as ranked version of the original symbolic attribute.
If means != NULL upon calling this function, then on return 'means' contains
binwise averages of the 'output' components values, which correspond to 
symbolic 'attnum' values present in the data.
There are as many components of 'means' as the arity of 'attnum'.
The caller must secure the space for 'means' externally.
Components of 'means' are stored according to the original order given by the
'attnum' definition.
If 'order' != NULL upon the call, then it contains the ordering of the 'attnum'
which has been used to compute ordinal values (or ranks) of the generated dyv.
Components of 'order' reflect the indices of symbolic values in the ordering chosen.
There are as many components of 'order' as the arity of 'attnum'.
The caller must secure the space for 'order' externally.
*******************/
dyv *mk_ordinal_dyv_from_symbolic_col( datset *ds, int attnum, dyv *output, 
                                       dyv *means, ivec *order)
{
  dyv *result = NULL;
  int n;
  /* int shift = 0; */
  if( ds_attnum_to_symbolicp(ds,attnum) && ((n=ds_num_rows(ds)) == dyv_size(output)))
  {
    int arity = ds_attnum_to_arity(ds,attnum);
    dyv *bins = mk_zero_dyv(arity);
    ivec *counts = mk_zero_ivec(arity);
    ivec *sortedcounts;
    double aux;
    int i, binindex;

    /* printf("arity of %12s (num %d)= %d\n",ds_attnum_to_name(ds,attnum),attnum,arity); */

    result = mk_dyv(n);

    for(i=0;i<n;i++) /* first calculate means */
    {
      binindex = ds_symbol_ref(ds,i,attnum);
      dyv_set(bins,binindex,dyv_ref(bins,binindex)+dyv_ref(output,i));
      ivec_set(counts,binindex,ivec_ref(counts,binindex)+1);
    }
    /* shift = 0; */
    
    for(i=0;i<arity;i++)
    {
      dyv_set(bins,i,( (ivec_ref(counts,i)) ? (dyv_ref(bins,i)/ivec_ref(counts,i)) : 0.0 ));
      /*  if( (ivec_ref(counts,i) == 0) )
	  shift++; // count the number of bins which do not contain any data */
    }
    /* bins contain averages of output values for each symbolic value of the input
       counts represent the number of instances of subsequent symbolic values
       and the same - the number of ties
       the ties should be resolved later, when writing to the result vector */

    /* now we've got the ordering */
    sortedcounts = mk_indices_of_sorted_dyv(bins); 
    if( means != NULL )
      copy_dyv(bins,means);
    if( order != NULL )
      copy_ivec(sortedcounts,order);

    fprintf_ivec(stdout,"      counts",counts,"\n");
    fprintf_ivec(stdout,"sortedcounts",sortedcounts,"\n");
    printf("bins: ");
    for(i=0;i<arity;i++)
      printf(" %g",dyv_ref(bins,ivec_ref(sortedcounts,i)));
    printf("\n");

    for(i=0;i<n;i++)
    {
      aux = ivec_ref(sortedcounts,ds_symbol_ref(ds,i,attnum));
      dyv_set(result,i,aux);
    }
	free_dyv(bins);
	free_ivec(sortedcounts);
	free_ivec(counts);
    }
  
  return(result);
}

