/* Copyright 2006 by Sean Luke and George Mason University Licensed under the Academic Free License version 3.0 See the file "LICENSE" for more information */ package sim.app.cto; import sim.util.Double2D; import sim.engine.*; public /*strictfp*/ class KMeansEngine implements Steppable { private static final long serialVersionUID = 1; final static double ALFA = 0.25; Double2D[] clusterPoints;// = new Double2D[ CooperativeObservation.NUM_AGENTS ]; boolean[] usable; // = new boolean[ CooperativeObservation.NUM_AGENTS ]; Double2D[] means;// = new Double2D[ CooperativeObservation.NUM_AGENTS ]; int[] labels;// = new int[ CooperativeObservation.NUM_TARGETS ]; int[] n;// = new int[ CooperativeObservation.NUM_AGENTS ]; double[] weight;// = new double[ CooperativeObservation.NUM_AGENTS ]; CooperativeObservation co; public KMeansEngine( CooperativeObservation co ) { this.co = co; clusterPoints = new Double2D[ CooperativeObservation.NUM_AGENTS ]; usable = new boolean[ CooperativeObservation.NUM_AGENTS ]; means = new Double2D[ CooperativeObservation.NUM_AGENTS ]; for( int i = 0 ; i < CooperativeObservation.NUM_AGENTS ; i++ ) { clusterPoints[i] = new Double2D(); means[i] = new Double2D(); } labels = new int[ CooperativeObservation.NUM_TARGETS ]; n = new int[ CooperativeObservation.NUM_AGENTS ]; weight = new double[ CooperativeObservation.NUM_AGENTS ]; } public Double2D getGoalPosition( int id ) { if( usable[id] ) return clusterPoints[id]; else return null; // for exploration purposes } public final double distanceBetweenPointsSQR( double x1, double y1, double x2, double y2 ) { return (x1-x2)*(x1-x2) + (y1-y2)*(y1-y2); } public void step( final SimState state ) { for( int i = 0 ; i < CooperativeObservation.NUM_AGENTS ; i++ ) { weight[i] = 0; if( means[i].x == 0 && means[i].y == 0 ) { clusterPoints[i] = means[i]; } means[i] = co.agentPos[i]; } for( int i = 0 ; i < CooperativeObservation.NUM_TARGETS ; i++ ) { int min = -1; double distance = -1; for( int j = 0 ; j < CooperativeObservation.NUM_AGENTS ; j++ ) { double currDist = distanceBetweenPointsSQR( co.targetPos[i].x, co.targetPos[i].y, co.agentPos[j].x, co.agentPos[j].y ); if( distance == -1 || distance > currDist ) { min = j; distance = currDist; } } labels[i] = min; } for( int i = 0 ; i < CooperativeObservation.NUM_AGENTS ; i++ ) { means[i] = new Double2D( 0.0, 0.0 ); n[i] = 0; } for( int i = 0 ; i < CooperativeObservation.NUM_TARGETS ; i++ ) { if( labels[i] != -1 ) { means[labels[i]] = new Double2D( means[labels[i]].x + co.targetPos[i].x, means[labels[i]].y + co.targetPos[i].y ); n[labels[i]]++; } } for( int i = 0 ; i < CooperativeObservation.NUM_AGENTS ; i++ ) { if( n[i] != 0 ) { means[i] = new Double2D( means[i].x/n[i], means[i].y/n[i] ); clusterPoints[i] = new Double2D( (1-ALFA)*clusterPoints[i].x + ALFA*means[i].x, (1-ALFA)*clusterPoints[i].y + ALFA*means[i].y ); usable[i] = true; } else { usable[i] = false; } } } }