/*
   File:        split.h
   Author:      Andrew W. Moore, Dan Pelleg
   Created:     Sun Apr  5 11:49:13 EDT 1998
   Description: splitting of kmeans-centers
   $Id: split.h,v 1.12 2004/01/19 21:11:29 dpelleg Exp $

   Copyright 1998, Carnegie Mellon University
*/


#ifndef SPLIT_H
#define SPLIT_H

#include "hrect.h"
#include "amiv.h"
#include "amdmex.h"
#include "simple_kdtree.h"
#include "traversal.h"

/* number of children born in a split */
#define N_CHILDREN (2)

/* sum of BIC score for all centers in ctrlist. If NULL, use all the live centers */
double bic_score(simple_kdtree *kd, vctr *centers, const kmeans_parm *parm,
                 const ivec *ctrlist);

/* modify set of centers, possibly splitting each live center
   into n_children children. Decision for each center is done indepenentaly,
   but number of new centers cannot exceed max_ctrs. */
void split_centers(simple_kdtree *kd, vctr *centers, const kmeans_parm *parm);

/* Pick a center to kill and delete it. Decision is based on bic score of 
   configuration of all other centers (unmoved). */
void delete_ctr(simple_kdtree *kd, vctr *centers, const kmeans_parm *parm,
                bool only_delete_if_improves_bic);

/*
  Compute a value related to the confidence we have in splitting
  a parent node into children nodes. The lower the value is, the more
  we are in favor of splitting (eg, for BIC scoring, negative values mean
  we should split).
*/
typedef double mk_birth_value_single_t(int parent_idx, const ivec *children,
                                       const nodestats *parent_stats,
                                       const nodestats *children_stats,
                                       const vctr *centers,
                                       dyvp_array *data_list);

/* for each center in mk_live_ctrs(centers), calculate a measure of confidence
   in keeping this center, versus splitting it into its children. The lower
   the value is, the better it seems to split.

   The function returns a dyv of the values in the corresponding indices.

   For BIC scoring, it returns the difference
   between the parent's BIC score and the BIC score of its (tentative) children.
*/

dyv *mk_birth_value(simple_kdtree *kd, vctr *centers, const kmeans_parm *parm);
dyv *mk_birth_value_backup(simple_kdtree *kd, vctr *centers, const kmeans_parm *parm);

/* Given a dyv and a ivec of its sorted indices (NULL will be filled in),
   find least index i such that value > dyv_ref(ivec_ref(sorted_dyv,i))
   If not found, returns -1
*/
int find_index_in_sorted_dyv(const dyv *dyv, const ivec *sorted_dyv, double val);

/* Given a dyv and a ivec of its sorted indices, and two numbers lo<=hi
   find least index i such that value > dyv_ref(ivec_ref(sorted_dyv,i))
   and also lo <= i <= hi
   If not found, returns -1
*/
int find_index_in_sorted_dyv_recursive(const dyv *dyv, const ivec *sorted_dyv,
									   double val, int lo, int hi);

#endif /* #ifndef SPLIT_H */
