import java.util.Random; import java.util.Vector; import java.util.Comparator; import java.util.Map; import java.util.TreeMap; import java.util.Iterator; /** *

* Creates a random flock of robots in an n-dimensional box *

* @author Michael Schuresko * @version %I%, %G% * @since 1.0 */ public class RandomConnectedInit implements IInitializer { int m_nNumAgents, m_nDim; int m_nNumAgentsActual; double [] m_arrLfMin; double [] m_arrLfMax; double m_lfConnectRad; double m_lfMinRad; double [] m_arrLfIniContState; ILogicVarBundle m_logicVarsToClone; IControlFunc m_controlFuncToClone; Random m_randomGen; boolean m_bVerbose; void setVerbosity() { m_bVerbose = false; } /** * constructor specifying number of agents and * dimensionality in which they live. * @param nAgents number of agents * @param nDim dimensionality in which they live */ public RandomConnectedInit(int nAgents, int nDim, double lfRad) { setVerbosity(); m_randomGen = new Random(); m_nNumAgents = nAgents; m_nDim = nDim; m_lfConnectRad = lfRad; m_arrLfMin = new double[nDim]; m_arrLfMax = new double[nDim]; for(int i = 0; i < nDim; ++i) { m_arrLfMin[i] = -0.5; m_arrLfMax[i] = 0.5; } m_logicVarsToClone = new NullLogicVarBundle(); m_controlFuncToClone = new ControlFuncDoNothing(nDim); m_lfMinRad = 0.0; } /** * constructor specifying number of agents, the * dimensionality in which they live, and the size * of the containing box along each dimension. * @param nAgents number of agents * @param arrLfSizes length, height, width, etc of box * in which agents live-arrLfSizes.length is dimensionality. */ public RandomConnectedInit(int nAgents, double [] arrLfSizes, double lfRad) { setVerbosity(); m_randomGen = new Random(); m_nNumAgents = nAgents; m_lfConnectRad = lfRad; m_nDim = arrLfSizes.length; m_arrLfMin = new double[m_nDim]; m_arrLfMax = new double[m_nDim]; for(int i = 0; i < m_nDim; ++i) { m_arrLfMin[i] = -0.5*arrLfSizes[i]; m_arrLfMax[i] = 0.5*arrLfSizes[i]; } m_logicVarsToClone = new NullLogicVarBundle(); m_controlFuncToClone = new ControlFuncDoNothing(m_nDim); m_lfMinRad = 0.0; } /** * constructor specifying number of agents, the * dimensionality in which they live, and the size * of the containing box along each dimension. * @param nAgents number of agents * @param arrLfMin min corner of box in which agents live. * @param arrLfMax max corner of box in which agents live. * */ public RandomConnectedInit(int nAgents, double [] arrLfMin, double [] arrLfMax, double lfRad) { setVerbosity(); m_randomGen = new Random(); m_nNumAgents = nAgents; m_lfConnectRad = lfRad; m_nDim = arrLfMin.length; m_arrLfMin = new double[m_nDim]; m_arrLfMax = new double[m_nDim]; for(int i = 0; i < m_nDim; ++i) { m_arrLfMin[i] = arrLfMin[i]; m_arrLfMax[i] = arrLfMax[i]; } m_logicVarsToClone = new NullLogicVarBundle(); m_controlFuncToClone = new ControlFuncDoNothing(m_nDim); m_lfMinRad = 0.0; } public void setMinRad(double lfMinRad) { m_lfMinRad = lfMinRad; } public void setDefaultIniVars(ILogicVarBundle copyMe) { m_logicVarsToClone = copyMe.makeCopy(); } public void setDefaultIniControlFunc(IControlFunc copyMe) { m_controlFuncToClone = copyMe.makeCopy(); } /** * Initial continuous state vector */ public double [] getInitContState() { resetState(); return m_arrLfIniContState; } public void resetState() { m_nNumAgentsActual = 0; while(m_nNumAgentsActual != m_nNumAgents) { m_arrLfIniContState = createIniContState(); m_nNumAgentsActual = m_arrLfIniContState.length/m_nDim; if(m_bVerbose) { System.out.println("there are "+m_nNumAgentsActual+" agents, should be "+m_nNumAgents); } } } double [] createIniContState() { Vector > vecPoints; vecPoints = getIniVec(); double [] arrLfOut = new double[vecPoints.size()*m_nDim]; for(int i = 0; i < vecPoints.size(); ++i) { for(int j = 0; j < m_nDim; ++j) { arrLfOut[i*m_nDim+j] = vecPoints.get(i).get(j); } } return arrLfOut; } Integer getDsuCount(Vector vecCounts, Vector vecReps, int i) { Integer objRep = getDsuRep(vecReps, i); return vecCounts.get(objRep.intValue()); } Integer getDsuRep(Vector vecReps, int i) { Integer objJ = new Integer(i); while(vecReps.get(objJ).compareTo(objJ) != 0) { objJ = vecReps.get(objJ); } Integer objResult = objJ; Integer objNext = objJ; for(objJ = new Integer(i); objJ.compareTo(objResult) != 0; objJ = objNext) { objNext = vecReps.get(objJ); vecReps.set(objJ.intValue(), objResult); } return objResult; } void doDsuMerge(Vector vecReps, Vector vecCounts, int i, int j) { Integer objIRep = getDsuRep(vecReps, i); Integer objJRep = getDsuRep(vecReps, j); if(objIRep.compareTo(objJRep) == 0) { return; } vecCounts.set(objJRep, vecCounts.get(objJRep)+ vecCounts.get(objIRep)); vecReps.set(objIRep.intValue(), objJRep); } public class VecComp implements Comparator> { public int compare(Vector v1, Vector v2) { if(v1.get(0) < v2.get(0)) { return -1; } if(v1.get(0) > v2.get(0) ) { return 1; } return 0; } public boolean equals(Vector v1, Vector v2) { return !((v1.get(0) > v2.get(0)) || (v1.get(0) < v2.get(0))); } } Vector > getIniVec() { Vector vecIndices = new Vector(m_nNumAgents, m_nNumAgents); Vector vecCounts = new Vector(m_nNumAgents, m_nNumAgents); TreeMap, Integer> mapPos = new TreeMap, Integer>(new VecComp()); boolean bConnected = false; int i; for(i = 0; !bConnected; ++i) { vecIndices.add(i, i); vecCounts.add(i,1); Vector vecNextPos = new Vector(m_nDim); int nAxis = 0; for(nAxis = 0; nAxis < m_nDim; ++nAxis) { Double objLfCurrPos = new Double(m_arrLfMin[nAxis] + m_randomGen.nextDouble()* (m_arrLfMax[nAxis]-m_arrLfMin[nAxis])); vecNextPos.add(nAxis, objLfCurrPos); } Iterator, Integer> > iPosPairs = null; if(m_lfMinRad > 0.0 && i > 0) { Vector vecMinCollideRange = new Vector(vecNextPos); Vector vecMaxCollideRange = new Vector(vecNextPos); vecMinCollideRange.set(0, vecMinCollideRange.get(0) - 2*m_lfMinRad); vecMaxCollideRange.set(0, vecMaxCollideRange.get(0) + 2*m_lfMinRad); boolean bCollides = false; iPosPairs = mapPos.subMap(vecMinCollideRange, vecMaxCollideRange).entrySet().iterator(); while(iPosPairs.hasNext()) { Map.Entry, Integer> currEntry = iPosPairs.next(); Integer nObjRep = currEntry.getValue(); Vector vecPosCmp = currEntry.getKey(); double lfDistSum = 0.0; for(nAxis = 0; nAxis < m_nDim; ++nAxis) { double lfAxisDist = vecNextPos.get(nAxis) - vecPosCmp.get(nAxis); lfDistSum += lfAxisDist*lfAxisDist; } if(lfDistSum < m_lfMinRad*m_lfMinRad && nObjRep.intValue() != i) { bCollides = true; } } if(bCollides) { --i; continue; } } mapPos.put(vecNextPos, i); Vector vecMinRange = new Vector(vecNextPos); Vector vecMaxRange = new Vector(vecNextPos); vecMinRange.set(0, vecMinRange.get(0) - 1.2*m_lfConnectRad); vecMaxRange.set(0, vecMaxRange.get(0) + 1.2*m_lfConnectRad); iPosPairs = mapPos.subMap(vecMinRange, vecMaxRange).entrySet().iterator(); // iPosPairs = mapPos.entrySet().iterator(); while(iPosPairs.hasNext()) { Map.Entry, Integer> currEntry = iPosPairs.next(); Integer nObjRep = currEntry.getValue(); Vector vecPosCmp = currEntry.getKey(); double lfDistSum = 0.0; for(nAxis = 0; nAxis < m_nDim; ++nAxis) { double lfAxisDist = vecNextPos.get(nAxis) - vecPosCmp.get(nAxis); lfDistSum += lfAxisDist*lfAxisDist; } if(lfDistSum < m_lfConnectRad*m_lfConnectRad && nObjRep.intValue() != i) { doDsuMerge(vecIndices, vecCounts, nObjRep, i); } } Integer nObjNumAgentsThisComp = getDsuCount(vecCounts, vecIndices, i); bConnected = (nObjNumAgentsThisComp >= m_nNumAgents); if(m_bVerbose) { System.out.println("UP to "+nObjNumAgentsThisComp +" agents, need "+m_nNumAgents); } } Vector > vecResult = new Vector >(vecCounts.get(vecCounts.size()-1)); Integer objSetRep = getDsuRep(vecIndices, vecIndices.size()-1); int nAddPos = 0; Vector vecOffset = null; Iterator, Integer> > iPosPairs = mapPos.entrySet().iterator(); while(iPosPairs.hasNext()) { Map.Entry, Integer> currEntry = iPosPairs.next(); Integer nObjI = getDsuRep(vecIndices, currEntry.getValue()); if(objSetRep.compareTo(nObjI) == 0) { vecResult.add(nAddPos, currEntry.getKey()); ++nAddPos; } } int nSize = vecResult.size(); // now we permute the result vector for better results!!! for(i = 0; i < vecResult.size(); ++i) { int nSwap = this.m_randomGen.nextInt(nSize-i)+i; Vector vecTmp = vecResult.elementAt(i); vecResult.set(i, vecResult.elementAt(nSwap)); vecResult.set(nSwap, vecTmp); } for(i = 0; i < vecResult.size(); ++i) { Vector vecAdjustMe = vecResult.get(i); if(vecOffset == null) { vecOffset = new Vector(vecResult.get(i).size()); for(int j = 0; j < vecResult.get(i).size(); ++j) { vecOffset.add(j, vecResult.get(i).get(j)); } } for(int j = 0; j < vecAdjustMe.size(); ++j) { vecAdjustMe.set(j, vecAdjustMe.get(j) - vecOffset.get(j)); } } return vecResult; } public IEnvironment getEnv() { return new NdTrivialEnv(m_arrLfMin, m_arrLfMax); } public int getNumAgents() { return m_nNumAgentsActual; } /** * convenient to have this... */ public StateBundle [] getInitDiscreteState() { StateBundle [] arrStates = new StateBundle[m_nNumAgentsActual]; if(m_bVerbose) { System.out.println("Initializing to "+m_nNumAgentsActual+" agents\n"); } for(int i = 0; i < m_nNumAgentsActual; ++i) { ILogicVarBundle currCopy = m_logicVarsToClone.makeCopy(); currCopy.setId(i); currCopy.init(); arrStates[i] = new StateBundle(currCopy, m_controlFuncToClone.makeCopy() ); } return arrStates; } public boolean isAgentCompatible(IAgent agent) { return (agent != null); } }