# mngclassify.awk
#
# do a dumb mng classification using
# +  ARGIND 1: network prototypes
# +  ARGIND 2: data to classify
#
# variables of interest:
# +  context_eta :  context weighting for distance calculation
# +  mix_c_w     :  weight for context/weight linear combination

BEGIN {

  ERR = "cat >& 2"

  if(context_eta == "") {
     context_eta = 0.5
     print "context_eta not given - set to " context_eta | ERR
  }

  if(mix_c_w == "") {
     mix_c_w = 0.5
     print "mix_c_w not given - set to " mix_c_w | ERR
  }
}


ARGIND == 1 {   # read net

  nn = $1

  for(i = 2; i <= NF; i++) pt[nn,i-1] = $i

  dim = (NF - 1) / 2

  ++neurons[nn]
  ++neu
}

ARGIND > 1 {

  if(first == 0) { # reset lastwinner / context
    ++first
    lastwinner = ++neu
    for(i = 1; i <= 2*dim; i++) pt[lastwinner,i] = 0.
  }

  if($NF <= -999.99)
    print lastwinner = neu
  else
    print lastwinner = winner()
}



function winner() {

  winx = 0
  minx = 1e20

  for(ex in neurons) {

    if(ex != lastwinner) {

      dx = (1. - context_eta) * distance_weight(ex) + context_eta * distance_context(ex)

      if(dx < minx) {
        minx = dx
        winx = ex
      }
    }
  }

  return winx
}


function distance_weight(neuronx) {

  resx = 0

  for(ix = 1; ix <= dim; ix++) {
    tmp = pt[neuronx,ix] - $ix
    resx += tmp * tmp
  }

  return resx
}


function distance_context(neuronx) {

  resx = 0

  for(ix = 1; ix <= dim; ix++) {
    tmp = mix_c_w * pt[lastwinner,ix+dim] + (1-mix_c_w) * pt[lastwinner,ix] - pt[neuronx,ix+dim]
    resx += tmp * tmp
  }

  return resx
}
