OK. Thanks to the help of posters on this board I have managed to get to the following stage with my code. Now I appreciate that asking people you don't know to scan your code for errors is probably almost as rude as expecting them to write it for you. I am using a Pentium 4, 2.4Ghz laptop, Microsoft Visual Studio on Win XP and all the nightmares that entails. The code seems to work but when I take the size value up high I get realloc failures...
OK the first function writes a header file of global variables:
Code:
headwrite.cpp
#include "stdafx.h"
#include<stdio.h>
#include<stdlib.h>
#define OUTPUT "C:\\matt\\nodes.h"
/* This program writes a header file that generates the N^2 nodes used in*
* the following program to use. It includes preprocessor shortcuts for *
* the names of the neighbour arrays. */
void write_header_file(char[], int, int);
int main(int argc, char* argv[])
{
char getside[20];
int side, size;
printf("Please input the side of the lattice:\n(ie \"5\" for a 25 node lattice)\n");
fgets(getside, 20, stdin);
side=atoi(getside);
size=side*side;
write_header_file(OUTPUT, side, size);
return 0;
}
void write_header_file(char filename[], int side, int size)
{
FILE *fptr;
int i;
fptr = fopen(filename, "w");
if(fptr == NULL){
fprintf(stderr, "Unable to open \"%s\" to write!\n", filename);
return;
}
fprintf(fptr, "/*Header file with node information*/\n\n");
fprintf(fptr, "/*General global quantities*/\n");
fprintf(fptr, "int side=%d;\nint size=%d;\n\n",side,size);
fprintf(fptr, "/*List of neighbour arrays*/\n");
for(i=0; i<size; i++)
fprintf(fptr, "int N%d[4];\n", i);
fprintf(fptr, "\n/*An array of neighbour arrays*/\n");
fprintf(fptr, "int *nbrs[]={N0,");
for(i=1; i<size-1; i++)
fprintf(fptr, " N%d,",i);
fprintf(fptr, " N%d};\n\n",size-1);
fprintf(fptr, "/*An array of flags, all initialised to zero*/\n");
fprintf(fptr, "int flags[]={0,");
for(i=1; i<size-1; i++)
fprintf(fptr, "0,");
fprintf(fptr, "0};\n\n");
fprintf(fptr, "/*A node degree array, where the ith element is the number *\n
*of links emanating from the ith node, initialised to that*\n
*of a regular square lattice*/\n\n");
fprintf(fptr, "int degree[]={4,");
for(i=1; i<size-1; i++)
fprintf(fptr, "4,");
fprintf(fptr, "4};\n");
return;
}
And here is an example of nodes.h for side=15. (Altho I have trimmed it to save a little space)
Code:
nodes.h
/*Header file with node information*/
/*General global quantities*/
int side=15;
int size=225;
/*List of neighbour arrays*/
int N0[4];
int N1[4];
int N2[4];
int N3[4];
int N4[4];
int N5[4];
int N6[4];
int N7[4];
int N8[4];
int N9[4];
int N10[4];
... etc ...
int N215[4];
int N216[4];
int N217[4];
int N218[4];
int N219[4];
int N220[4];
int N221[4];
int N222[4];
int N223[4];
int N224[4];
/*An array of neighbour arrays*/
int *nbrs[]={N0, N1, N2, N3, N4, N5, N6, N7, N8, N9, N10, ... ,
N215, N216, N217, N218, N219, N220, N221, N222, N223, N224};
/*An array of flags, all initialised to zero*/
int flags[]={0,0,0, ..., 0,0,0};
/*A node degree array, where the ith element is the number *
*of links emanating from the ith node, initialised to that*
*of a regular square lattice */
int degree[]={4,4,4,...,4,4,4};
And then the main program:
Code:
carla.cpp
/************************************
* CARLA *
* C Adaptation: Random Links Added *
* *
* by Matt 13, August 2003 *
************************************/
#include "stdafx.h"
#include<stdio.h>
#include<stdlib.h>
#include<math.h>
#include<time.h>
#include<gsl/gsl_rng.h>
#include"C:\matt\nodes.h"
void create_lattice(int);
void add_random_link(int);
void initialise_flags(int);
void save_flags(int[]);
void restore_flags(int[]);
void setup_infectives(int[], int);
int get_flag_type(int);
void do_algorithm(int[], int[], int, double);
void update_flags(int[]);
void dump_stats(int, int, int, int, int, int, char[]);
gsl_rng * seed = gsl_rng_alloc (gsl_rng_ranlux389);
#define OUTPUT "C:\\matlab6p1\\work\\carla.m"
int main(int argc, char* argv[])
{
/*DECLARATIONS - PRE SHELL INTERACTION*/
int iterate, enditerate, t, endtime;
int i;
int init_infec, infec;
int no_of_s, no_of_i, no_of_r;
double p, alpha;
int *infectives;
int *temp;
int *restore;
char getits[20];
char gettime[20];
char getp[20];
char getalpha[20];
char getinfec[20];
srand(time(NULL));
/*SHELL INTERACTION*/
printf("There are %d nodes.\n", size);
printf("To change this, please run the headerwrite program.\n");
printf("Please enter the number of iterates required:\n");
fgets(getits, 20, stdin);
enditerate=atoi(getits);
printf("Please enter the number of time steps required:\n");
fgets(gettime, 20, stdin);
endtime=atoi(gettime);
printf("Please enter the probability p that a rewired link exists:\n");
printf("NB: Entering p=0 will give the original lattice.\n");
fgets(getp, 20, stdin);
p=atof(getp);
while(p<0 || p>1){
printf("Probability must be between 0 and 1!\n");
printf("Please enter the probability (p) that a rewired link exists:\n");
fgets(getp, 20, stdin);
p=atof(getp);
}
printf("Please enter the probability (alpha) that an infective becomes\n");
printf("a stifler upon contact with another infective or stifler:\n");
fgets(getalpha, 20, stdin);
alpha=atof(getalpha);
while(alpha<0 || alpha>1){
printf("Probability must be between 0 and 1!\n");
printf("Please enter the probability alpha:\n");
fgets(getalpha, 20, stdin);
alpha=atof(getalpha);
}
printf("Please enter a non-zero number of initially infected nodes:\n");
fgets(getinfec, 20, stdin);
init_infec=atoi(getinfec);
while(init_infec>size){
printf("Number of initial infectives cannot exceed the total number of nodes!\n");
printf("Please enter the number of initially infected nodes:\n");
fgets(getinfec, 20, stdin);
init_infec=atoi(getinfec);
}
/*DECLARATIONS - POST SHELL INTERACTION*/
infectives=(int*)calloc(init_infec, sizeof(int));
temp=(int*)calloc(size, sizeof(int));
restore=(int*)calloc(size, sizeof(int));
/*MAIN PROGRAM CENTRE*/
create_lattice(size);
for(i=0;i<size;i++){
if(gsl_rng_uniform(seed)<p){
add_random_link(i);
}
}
initialise_flags(init_infec);
temp=flags;
save_flags(restore);
for(iterate=0; iterate<enditerate; iterate++){
for(t=0; t<endtime; t++){
if((t==0)&&(iterate!=0)){
restore_flags(restore);
temp=flags;
}
infec=get_flag_type(1);
infectives=(int*)calloc(infec, sizeof(int));
setup_infectives(infectives, infec);
do_algorithm(infectives, temp, infec, alpha);
update_flags(temp);
no_of_s=get_flag_type(0);
no_of_i=get_flag_type(1);
no_of_r=get_flag_type(2);
dump_stats(t, endtime-1, iterate, no_of_s, no_of_i, no_of_r, OUTPUT);
free(infectives);
}
}
free(temp);
free(restore);
return 0;
}
void create_lattice(int size)
{
/*******************************************************
* MODIFIES THE NEIGHBOUR ARRAYS CREATED IN THE HEADER *
*FILE AND MAKES THEM CONSISTENT WITH A REGULAR LATTICE*
*******************************************************/
int i;
for(i=0; i<size; i++){
if(i<=side-1) /*up*/
nbrs[i][0]=(side*side)-(side-i);
else
nbrs[i][0]=i-side;
if(i%side==side-1) /*right*/
nbrs[i][1]=i-(side-1);
else
nbrs[i][1]=i+1;
if(i>side*(side-1) && i<side*side) /*down*/
nbrs[i][2]=i-(side*(side-1));
else
nbrs[i][2]=i+side;
if(i%side==0) /*left*/
nbrs[i][3]=i+side-1;
else
nbrs[i][3]=i-1;
}
printf("The regular lattice has been set up.\n");
return;
}
void add_random_link(int origin)
{
/*(WITH PROBABILITY p) ADD A LINK TO A RANDOM NODE TO "ORIGIN"*/
int target=rand()%size;
while(target==origin)
target=rand()%size;
printf("Target is %d.\n", target);
int len=degree[origin];
int len2=degree[target];
int *tmp;
int *tmp2;
tmp=(int*)realloc(nbrs[origin], sizeof(int)*(len+1));
if(tmp!=NULL){
nbrs[origin]=tmp;
nbrs[origin][len]=target;
degree[origin]++;
printf("The degree of node %d is now %d.\n", origin, degree[origin]);
}
else{
printf("Failure in realloc.\n");
return;
}
free(tmp);
tmp2=(int*)realloc(nbrs[target], sizeof(int)*(len2+1));
if(tmp2!=NULL){
nbrs[target]=tmp2;
nbrs[target][len2]=origin;
degree[target]++;
printf("The degree of node %d is now %d.\n", target, degree[target]);
}
else{
printf("Failure in realloc.\n");
return;
}
free(tmp2);
printf("There is a new link between %d and %d.\n",origin, target);
return;
}
void initialise_flags(int init_infec)
{
/*SETS THE FLAGS OF init_infec NODES TO 1*/
int i=0;
int j;
while(i<init_infec){
j=rand()%size;
flags[j]=1;
i++;
}
printf("Flags have been initialised.\n");
return;
}
void save_flags(int restore[])
{
/*SAVE FLAGS FOR RESTORE AT NEXT ITERATION*/
int i;
for(i=0; i<size; i++)
restore[i]=flags[i];
printf("Flags have been saved.\n");
return;
}
void restore_flags(int restore[])
{
/*RESTORES FLAGS TO INITIAL VALUES*/
int j;
for(j=0; j<size; j++)
flags[j]=restore[j];
printf("Flags have been restored.\n");
return;
}
void setup_infectives(int infectives[], int check)
{
/*SETS UP THE INFECTIVES ARRAY*/
int i=0;
int j=0;
while(i<size){
if(flags[i]==1){
if(j<check){
infectives[j]=i;
j++;
}
}
i++;
}
printf("Infectives array has been set up.\n");
return;
}
int get_flag_type(int flagtype)
{
/*RETURNS NUMBER OF NODES WITH FLAG "flagtype"*/
int count=0;
int i;
for(i=0; i<size; i++){
if(flags[i]==flagtype){
count++;
}
}
return count;
}
void do_algorithm(int infectives[], int temp[], int infec, double alpha)
{
/*PERFORMS ALGORITHM LOOPING OVER INFECTIVE NODES*/
int i,r;
for(i=0;i<infec;i++){
r=rand()%degree[infectives[i]];
if(flags[nbrs[infectives[i]][r]]==0)
temp[nbrs[infectives[i]][r]]=1;
else{
if(gsl_rng_uniform(seed)<alpha)
temp[infectives[i]]=2;
}
}
printf("Algorithm applied.\n");
return;
}
void update_flags(int temp[])
{
/*UPDATES THE FLAGS ARRAY AFTER A TIME STEP*/
int i;
for(i=0;i<size;i++)
flags[i]=temp[i];
printf("Flags updated.\n");
return;
}
void dump_stats(int time, int endt, int it, int s, int i, int r, char filename[])
{
/*WRITES DATA TO AN M-FILE FOR MATLAB PLOTS*/
FILE *fptr;
if(time==0&&it==0)
fptr=fopen(filename, "w");
else
fptr=fopen(filename, "a");
if(fptr==NULL){
fprintf(stderr, "Unable to open \"%s\" to append.\n", filename);
return;
}
if(time==0)
fprintf(fptr, "A%d=[%d, %d, %d;\n", it, s, i, r);
if(time==endt){
fprintf(fptr, "%d, %d, %d]\n", s, i, r);
printf("Iteration number: %d. Total number of nodes infected is: %d\n", it, i+r);
}
else
fprintf(fptr, "%d, %d, %d;\n", s, i, r);
fclose(fptr);
return;
}
I'm aware that I only listed one problem with the code above but there are a few more issues - some of them so basic I intend to sort them out myself. I apologise in advance for the size (particularly the width) of this post.