#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>

#define TRUE 1
#define FALSE 0

#define MAXRUN 10

int MAXINS;
int M;
float density;
float mu;
float sigma;
int C_LO;
int C_HI;

void floyd(int **);

int main(int argc, char** argv)
{
int i, j, run;
int *F, **C;
FILE *fp;
char filename[12];
char run_no[3];
int instance;
int INFINITY;
float nz, z;

	if (argc == 1)
	{
		printf("Usage: grgen  <M> <density> <F_mu> <F_sigma> <C_LO> <C_HI> <prefix> <num_prob> \nAll Integers please.\n");
   		exit(0);
	}
	M = atoi(argv[1]);
	density = atof(argv[2]);
	mu = atof(argv[3]);
	sigma = atof(argv[4]);
	C_LO = atoi(argv[5]);
	C_HI = atoi(argv[6]);

	MAXINS = atoi(argv[8]);
	/*printf("%d %s problems: Size M = %d density = %d, F = (%d, %d), C = (%d, %d)\n\n",MAXINS, filename, M, density, F_LO, F_HI, C_LO, C_HI);*/

	INFINITY = M*401;

	F = (int *)calloc(M, sizeof(int));
	C = (int **)calloc(M, sizeof(int *));
	for (i = 0; i < M; i++)
		C[i] = (int *)calloc(M, sizeof(int));
	srand(123456);
	for (instance = 1; instance <= MAXINS; instance++)
	{
	for (run = 1; run <= MAXRUN; run++)
	{
		strcpy(filename, argv[7]);
		itoa(instance, run_no, 10);
		strcat(filename, run_no);
		itoa(run, run_no, 10);
		strcat(filename, ".");
		strcat(filename, run_no);

		printf("Building file %s ", filename);

		for (i = 0; i < M; i++)
		{
			z = rand()*1.0/RAND_MAX;
			if (z < 1.0/6)
				nz = 6.0*0.02275*z;
			else if (z < 1.0/3)
				nz = 0.02275 + (0.15866 - 0.02275)*(z - 1.0/6)*6.0;
			else if (z < 2.0/3.0)
				nz = 0.15866 + (0.84134 - 0.15866)*(z - 1.0/3)*6.0;
			else if (z < 5.0/6.0)
				nz = 0.84134 + (0.97725 - 0.84134)*(z - 2.0/3)*6.0;
			else
				nz = 0.97725 + (1.0 - 0.97725)*(z - 5.0/6)*6.0;

			F[i] = (int)(100* (mu - 3.0 * sigma + nz * 6*sigma));
			if (F[i] < 0.0) F[i] = 0.0;
			for (j = 0; j < M; j++)
				if ((int)(rand()*100./RAND_MAX) <= density)
					C[i][j] = (int)(rand()*1.0/RAND_MAX * (C_HI - C_LO) + C_LO);
				else
					C[i][j] = INFINITY;
		}

		floyd(C);
		fp = fopen(filename, "w");
		fprintf(fp, "FILE: %s\n",filename);
		fprintf(fp, "%d %d 0\n", M, M);
		for (i = 0; i < M; i++)
		{
			fprintf(fp, "%d %d ", i+1, F[i]);
			for (j = 0; j < M; j++)
				fprintf(fp, "%d ", C[i][j]);
			fprintf(fp, "\n");
		}
		fclose(fp);
		printf(". . . Done\n");
	}
	}

	return 0;
}

void floyd(int **A)
{
int FLAG;
int i, j, k;
int **B;
	B = (int **)calloc(M, sizeof(int *));
	for (i = 0; i < M; i++)
		B[i] = (int *)calloc(M, sizeof(int));

	for (i = 0; i < M; i++)
		for (j = 0; j < M; j++)
			B[i][j] = A[i][j];

	FLAG = TRUE;
	while (FLAG == TRUE)
	{
		for (i = 0; i < M; i++)
			for (j = 0; j < M; j++)
				B[i][j] = A[i][j];

		FLAG = FALSE;
		for (i = 0; i < M; i++)
		{
			for (j = 0; j < M; j++)
			{
				for (k = 0; k < M; k++)
				{
					if (B[i][k] + B[k][j] < B[i][j])
					{
						FLAG = TRUE;
						A[i][j] = B[i][k] + B[k][j];
					}
				}
			}
		}
	}
	return;
}
