// ********************************************************************** // author : Alexander Yong // email : ayong@umich.edu // version : April 30, 2003 // // Code for approximating number of spanning forests of a graph, based on // "Random weighting, asymptotic counting and inverse isoperimetry" by: // Alexander Barvinok and Alex Samorodnitsky. // // Standard Kruskal algorithm implementation. // ********************************************************************** #include #include #include #include #include #include #include #include const int MAXDIM = 300; // maximal number of vertices of G const int MAXEDGES = 10000; // make at least MAXDIM choose 2 const int MAXIMAL_RAND = RAND_MAX; const float BIG_NEGATIVE_FOR_NONEDGE = -6789; const float SOLVER_ACCURACY = 0.000001; const float PI = 3.14159254; // ---------------------------------------------------------------------- // KRUSKAL'S ALGORITHM FUNCTIONS int U[MAXDIM]; int used_nonedge = 0; float search(float i){ int j; j = (int)i; while (U[j] != j) j = U[j]; return (j); } float kruskal(float W[MAXDIM][MAXDIM], int N, int num_edges_forest, int M){ float E[MAXEDGES][3]; // complete set of edges float F[MAXEDGES][3]; // set of edges in max span. forest int num_edges = 0; int next_edge = 0; float weight = 0; int i, j, k, q; float a, b, c; // initialize set of edges k = 0; for (i = 0; i < N; i++){ for (j = 0; j < N; j++){ if (j > i){ E[k][0] = i; // first vertex of edge E[k][1] = j; // second vertex of edge E[k][2] = W[i][j]; // weight of edge k=k+1; } } } // bubblesort set of edges in non-increasing order by weight for (i = M - 1; i > 0; i--){ for (j = 0; j < i; j++){ if (E[j][2] < E[j+1][2]){ a = E[j][0]; b = E[j][1]; c = E[j][2]; E[j][0] = E[j+1][0]; E[j][1] = E[j+1][1]; E[j][2] = E[j+1][2]; E[j+1][0] = a; E[j+1][1] = b; E[j+1][2] = c; } } } // create N disjoint subsets for(q=0;qSOLVER_ACCURACY){ mid_point=(left_point+right_point)/2; d1=(left_point+mid_point)/2; d2=(right_point+mid_point)/2; value1=t*d1-log(PI*d1/(sin(PI*d1))); value2=t*d2-log(PI*d2/(sin(PI*d2))); if(value1>value2){ right_point=mid_point; max_value=value1; } else{ left_point=mid_point; max_value=value2; } interval_range=right_point-left_point; } Hoft= max_value; return(Hoft); } float upper_logistic(float avg_GAMMA, int k){ float upper_ans; upper_ans=avg_GAMMA; return(upper_ans); } float lower_logistic(float avg_GAMMA, int k){ float lower_ans; lower_ans=(k-1)*H_fn_logistic((float)avg_GAMMA/(k-1)); return(lower_ans); } // ---------------------------------------------------------------------- int main(){ using std::string; long int seed = time(0); // random seed int ii,jj,kk; int num_vertices, num_edges_forest; string fileName; ifstream inFile; int matrix[MAXDIM][MAXDIM]; // vertex 0-1 incidence matrix float weights[MAXDIM][MAXDIM]; float GAMMA, avg_GAMMA; float max_weight_forest; float upper_bound,lower_bound; float prob; int m; // number of times to sample int complete_num_edges; // equals (num_vertices choose 2) int dist_type; // which distribution to use cout << "--------------------------------------------------------------\n"; cout << "This program takes a given graph G and embeds it into the\n"; cout << "hypersimplex. It then estimates the number of spanning forests\n"; cout << "of G by assigning random weights to each edge of G, and\n"; cout << "applying Kruskal's algorithm to find a maximal weight spanning\n"; cout << "forest. This is done m times and the resulting average estimates\n"; cout << "the function GAMMA. Then upper and lower bounds for the number\n"; cout << "of spanning forests are calculated.\n"; cout <<"--------------------------------------------------------------\n\n\n"; cout << "Enter the number of times m to sample: \n"; cin >> m; cout << "\n"; while(m<=0){ cout << "This number must be greater than zero.\n"; cout << "Enter the number of times m to sample: \n"; cin >> m; cout << "\n"; } cout << "Enter the number of vertices in the graph G\n"; cin >> num_vertices; cout << "\n"; cout << "Enter the number of edges in the forest.\n"; cout << "This must be less than the number of vertices.\n"; cin >> num_edges_forest; cout << "Enter the name of the input file:\n"; cin >> fileName; inFile.open(fileName.c_str(), ios::in); while(!inFile){ cout << "File open error: '" << fileName << "' "; cout <<"Try again.\n"; inFile.close(); cout << "Enter the name of the input file:\n"; cin >> fileName; inFile.open(fileName.c_str(), ios::in); } // read in the matrix from inFile for(ii=0; ii> matrix[ii][jj]; } } cout << "Which distribution?:\n"; cout << "1. Exponential\n"; cout << "2. Logistic\n"; cout << "Enter 1 or 2\n"; cin >> dist_type; while(dist_type!=1 && dist_type!=2){ cout << "Please choose distribution 1 or 2.\n"; cin >> dist_type; } complete_num_edges=(int)(num_vertices)*(num_vertices-1)/2; // now sample weights and run Kruskal m times GAMMA=0; srand((unsigned)time(NULL)); for(kk=0;kk