Ejemplo n.º 1
0
void ExampleKMeans(int argIndex, int argc, char **argv) {	
	char filename[FILENAME_MAX];
	CLUSTER_ALOG *kmeans;
	CLUSTER_ITEM *dataset;
	int iteration;

	LocateFile("iris.csv",filename,FILENAME_MAX);
	kmeans = CreateKMeans(3,4);
	dataset = KMeansLoadCSV(filename,4,0,4);

	/* Note, it is not necessary to delete the dataset list, it will be deleted
	   when the clusters are deleted.  However, if you did need to delete it, pre-clustering,
	   the following command would do that.

		KMeansDeleteList(dataset); */

	/* To display the dataset, pre-clustering, use: 
	
	   KMeansDumpList(stdout,dataset,4); */

	
	KMeansInitForgy(kmeans,dataset);
	
	iteration = 1;
	while(!KMeansIteration(kmeans)) {
		printf("Iteration #%i\n",iteration);
		iteration++;
	}
	KMeansDump(stdout,kmeans);

	DeleteKMeans(kmeans);
}
Ejemplo n.º 2
0
void CAttackHandler::UpdateKMeans() {
	const int arrowDuration = 300;
	{//want local variable definitions
		//get positions of all friendly units and put them in a vector (completed buildings only)
		int numFriendlies = 0;
		vector<float3> friendlyPositions;
		int friendlies[MAXUNITS];
		numFriendlies = ai->cb->GetFriendlyUnits(friendlies);
		for (int i = 0; i < numFriendlies; i++) {
			int unit = friendlies[i];
			CUNIT* u = ai->MyUnits[unit];
			//its a building, it has hp, and its mine (0)
			if (this->UnitBuildingFilter(u->def()) && this->UnitReadyFilter(unit) && u->owner() == 0) {
				friendlyPositions.push_back(u->pos());
			}
		}
		//hack to make it at least 1 unit, should only happen when you have no base:
		if (friendlyPositions.size() < 1) {
			//it has to be a proper position, unless there are no proper positions.
			if (numFriendlies > 0 && ai->cb->GetUnitDef(friendlies[0]) && ai->MyUnits[friendlies[0]]->owner() == 0) friendlyPositions.push_back(ai->cb->GetUnitPos(friendlies[0]));
			else friendlyPositions.push_back(float3(RANDINT % (ai->cb->GetMapWidth()*8), 1000, RANDINT % (ai->cb->GetMapHeight()*8))); //when everything is dead
		}
		//calculate a new K. change the formula to adjust max K, needs to be 1 minimum.
		this->kMeansK = int(min((float)(KMEANS_BASE_MAX_K), 1.0f + sqrtf((float)numFriendlies+0.01f)));
		//iterate k-means algo over these positions and move the means
		this->kMeansBase = KMeansIteration(this->kMeansBase, friendlyPositions, this->kMeansK);
		//now, draw these means on the map
		int lineWidth = 25;
		int lineWidth2 = 3;
//		for (int i = 0; i < kMeansK; i++) {
//			//ai->cb->CreateLineFigure(kMeansBase[i]+float3(0,400,0), kMeansBase[i], lineWidth, 1, arrowDuration, RANDINT % 59549847);
//		}
	}
	
	//update enemy position k-means
	//get positions of all enemy units and put them in a vector (completed buildings only)
	int numEnemies = 0;
	vector<float3> enemyPositions;
	int enemies[MAXUNITS];
	numEnemies = ai->cheat->GetEnemyUnits(enemies);
	for (int i = 0; i < numEnemies; i++) {
		const UnitDef *ud = ai->cheat->GetUnitDef(enemies[i]);
		if (this->UnitBuildingFilter(ud)) { // && this->UnitReadyFilter(unit)) {
			enemyPositions.push_back(ai->cheat->GetUnitPos(enemies[i]));
//			//L("AttackHandler debug: added enemy building position for k-means " << i);
		}
	}
	//hack to make it at least 1 unit, should only happen when you have no base:
	if (enemyPositions.size() < 1) {
		//it has to be a proper position, unless there are no proper positions.
		if (numEnemies > 0 && ai->cheat->GetUnitDef(enemies[0])) enemyPositions.push_back(ai->cheat->GetUnitPos(enemies[0]));
		else enemyPositions.push_back(float3(RANDINT % (ai->cb->GetMapWidth()*8), 1000, RANDINT % (ai->cb->GetMapHeight()*8))); //when everything is dead
	}
	//calculate a new K. change the formula to adjust max K, needs to be 1 minimum.
	this->kMeansEnemyK = int(min(float(KMEANS_ENEMY_MAX_K), 1.0f + sqrtf((float)numEnemies+0.01f)));
//		//L("AttackHandler: doing k-means k:" << kMeansK << " numPositions=" << numFriendlies);
	//iterate k-means algo over these positions and move the means
	this->kMeansEnemyBase = KMeansIteration(this->kMeansEnemyBase, enemyPositions, this->kMeansEnemyK);
	//now, draw these means on the map
	int lineWidth = 25;
//	for (int i = 0; i < kMeansEnemyK; i++) {
//		//L("AttackHandler debug: painting k-means for enemy nr " << i);
//		//ai->cb->CreateLineFigure(kMeansEnemyBase[i]+float3(300,300,0), kMeansEnemyBase[i], lineWidth, 1, arrowDuration, (RANDINT % 49584985));
//	}

	//base k-means and enemy base k-means are updated.	
	//approach: add up (max - distance) to enemies
	vector<float> proximity;
	proximity.resize(kMeansK, 0.0000001f);
	const float mapDiagonal = sqrt(pow((float)ai->cb->GetMapHeight()*8,2) + pow((float)ai->cb->GetMapWidth()*8,2) + 1.0f);

	for (int f = 0; f < kMeansK; f++) {
		for (int e = 0; e < kMeansEnemyK; e++) {
			proximity[f] += mapDiagonal - kMeansBase[f].distance2D(kMeansEnemyBase[e]);
		}
	}

	//sort kMeans by the proximity score
	float3 tempPos;
	float temp;
	for (int i = 1; i < kMeansK; i++) { //how many are completed
		for (int j = 0; j < i; j++) { //compare to / switch with
			if (proximity[i] > proximity[j]) { //switch
				tempPos = kMeansBase[i];
				kMeansBase[i] = kMeansBase[j];
				kMeansBase[j] = tempPos;
				temp = proximity[i];
				proximity[i] = proximity[j];
				proximity[j] = temp;
			}
		}
	}
	//okay, so now we have a kMeans list sorted by distance to enemies, 0 being risky and k being safest.

	//now, draw these means on the map
	for (int i = 1; i < kMeansK; i++) {
		//ai->cb->CreateLineFigure(kMeansBase[i-1]+float3(0,100,0), kMeansBase[i]+float3(0,100,0), lineWidth, 1, arrowDuration, (RANDINT % 59549847));
	}
}