package genesom;


public class NeighbourhoodFunction
  extends SOMDecayFunction
{

  protected DecayModel shrinkmodel;

  protected double sm_from;
  protected double sm_to;
  protected double sm_eta;
  protected double sm_span;

  protected int cycles = 0;


  public NeighbourhoodFunction() { to = 0.; }

  public NeighbourhoodFunction(double from, double to) {
    super(from,to);
  }

  public NeighbourhoodFunction(double from, double to, double eta) {
    super(from, to, eta);
  }


  // set methods 2b called by property intitialization

  public void setNeighbourhood_from(double d) { from = 1.; /* !!! */ }
  public double getNeighbourhood_from() { return from; }

  public void setNeighbourhood_to(double d) { to = d; }
  public double getNeighbourhood_to() { return to; }

  public void setNeighbourhood_eta(double d) { eta = d; }
  public double getNeighbourhood_eta() { return eta; }

  public void setNeighbourhood_model(String dm) { setDecayModel(dm); }


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


  public void setNeighbourhood_shrink_from(double d) { sm_from = d; }
  public double getNeighbourhood_shrink_from() { return sm_from; }

  public void setNeighbourhood_shrink_to(double d) { sm_to = d; }
  public double getNeighbourhood_shrink_to() { return sm_to; }

  public void setNeighbourhood_shrink_eta(double d) { sm_eta = d; }
  public double getNeighbourhood_shrink_eta() { return sm_eta; }


  public void setSOMEnviroment(SOM som) {

    if(shrinkmodel == null)
      throw new RuntimeException("Neighbourhood shrink model not specified!");

    from = 1.;  // winner neuron always full update

    super.setSOMEnviroment(som);

    shrinkmodel.setFrom(sm_from);
    shrinkmodel.setTo(sm_to);
    shrinkmodel.setEta(sm_eta);

    if(sm_span <= 0.) shrinkmodel.setSpan(sm_span = som.maxcycles);

    if(shrinkmodel.init())
      throw new RuntimeException("NeighbourhoodFunction not properly inited!");
  }


  public void setNeighbourhood_shrink_model(String dm) {

    try {

      shrinkmodel = (DecayModel)Class.forName(
       (dm.indexOf('.') < 0 ?
        this.getClass().getPackage().getName() + "." : "") + dm).newInstance();

    } catch(Exception e) { e.printStackTrace(); throw new RuntimeException(e); }
  }


  public double value(double x) {     // returns value between 0...1

    if(cycles != som.cycles) {

      from = shrinkmodel.get(cycles = som.cycles);

      decmo.setSpan(from);

      if(decmo.init())
        throw new RuntimeException("Neighbourhood shrink error!");
    }

    double tmp = decmo.get(x);

    return tmp < 0. ? 0. : (tmp > 1. ? 1. : tmp);
  }
}
