I am trying to create a function that will take in the positions of numerous bodies moving in circular motion, and output their orbital periods. Each body is stored in a struct which contains its X, Y and Z co-ordinate (as well as some other information I don't need for this specific task).
My current function for doing this is:
double calc_period(Body *bodies, double t, int Nbodies, int i)
{
double orbit_angle[Nbodies];
double initial_angle[Nbodies];
double last_angle[Nbodies]
double last_time[Nbodies];
double half_step[Nbodies];
double running_total[Nbodies];
double orbitN[Nbodies];
double average_period[Nbodies];
orbit_angle[i] = atan(bodies[i].r[Y] / bodies[i].r[X]);
if (t==0) {
//Initialise all the variables to 0 the first time through
last_angle[i] = 0;
initial_angle[i] = orbit_angle[i];
orbitN[i] = 0;
half_step[i] = 1;
}
if (last_angle[i] < initial_angle[i] && orbit_angle[i] > initial_angle[i]) {
if (half_step[i] == 0) {
if (orbitN[i]==0) {
last_t[i] = t;
running_total[i] = t;
} else {
running_total[i] += t - last_t[i];
last_t[i] = t;
}
orbitN[i]++;
average_period[i] = running_total[i] / (DAYS_TO_SECS * orbitN[i]);
half_step[i] = 1;
} else if (half_step[i] == 1) {
half_step[i] = 0;
}
}
last_angle[i] = orbit_angle[i];
return average_period[i];
}
and this function is called in main like so:
for (double j = 0; j < max_time; j += timestep) {
update_positions(bodies, Nbodies, j);
for (int i = 0; i < Nbodies; i++) {
average_period[i] = calc_period(bodies, j, Nbodies, i);
if (j > max_time - timestep) {
printf("%s average period: %lg\n", bodies[i].name, average_period[i]);
}
}
}
and the problem that I'm having is that of course when the calc_period function finishes, the variables within are destroyed, so it cannot remember what initial_angle, last_angle or last_t were, so doesn't work. However I'm struggling to come up with a solution for this. If anyone can give any guidance it would be much appreciated.
Any data in the stack is volatile within function calls. The space in the stack you are using now will be replaced on future function calls, so functions on the stack should be used just until the function ends.
For your problem different methods exists.
You can create a struct as a global variable which will be stored in BSS, you can create a global pointer pointing to your struct on dynamic memory, allocated with functions like malloc().
Also you can create a static variable so on future calls to that function you can use it.
The best solution would be either defining a static pointer to malloc() where your struct resides, or doing the same on a global variable as a pointer.
Related
I want to stop the for loop for validation set when the current accuracy is less than previous accuracy calculated in the loop.
for (int j = 0; j < epochs; j++) {
DPRINT("Epoch %d: 000%%", j + 1);
DTIME_START_COUNTER;
for (int i = 0; i < train_data->m; i++) {
X->data[0] = train_data->data[i];
y->data[0] = train_labels->data[i];
backprop(network, X, y);
if (i % (int)mini_batch_size == 0 || i == train_data->m - 1) {
DPRINT("\b\b\b\b%03.0f%%", i * 100 / (double)(train_data->m - 1));
apply_derivation(network, mini_batch_size, training_rate);
}
}
DPRINT(" Eval accuracy: %.2f%%\n",
network_accuracy(network, eval_data, eval_labels, NULL));
}
Yes break, but I want to store accuracy (from network_accuracy) in array and compare the value of two consecutive iterations
You need to do something twice, or just finer control, do an extract method refactoring and put the code in a function. Then call that function.
// Put allocation of structs into their own function.
// All the necessary allocation goes in here.
Network *Network_new() {
// If you simply did `Network network` it would be automatically
// freed when the function exits. To return a complex value,
// allocate it on the heap.
return malloc(sizeof(Network);
}
// Pass in everything it needs. No globals.
// I'm just guessing at the types.
// A proliferation of arguments might suggest the need for a struct
// to gather them together.
Network *do_the_thing(
Data *train_data,
Data *train_labels,
Data *x, Data *y,
size_t mini_batch_size,
int training_rate
) {
// Allocate a new Network struct.
Network *network = Network_new();
for (int i = 0; i < train_data->m; i++) {
x->data[0] = train_data->data[i];
y->data[0] = train_labels->data[i];
backprop(network, x, y);
if (i % (int)mini_batch_size == 0 || i == train_data->m - 1) {
DPRINT("\b\b\b\b%03.0f%%", i * 100 / (double)(train_data->m - 1));
apply_derivation(network, mini_batch_size, training_rate);
}
}
// Presumably backprop and apply_derivation have changed network.
return network;
}
// Allocate space for two Network pointers.
Network *networks[2];
for(int i = 0; i < 2; i++) {
// Save the results to the array.
networks[i] = do_the_thing(
train_data,
train_labels,
x, y,
mini_batch_size,
training_rate
);
}
// Compare networks[0] and networks[1] as you like.
// Then free them.
for(int i = 0; i < 2; i++) {
free(network[i]);
}
Alternatively, pass in a pre-allocated return value. This is more flexible, but requires a bit more work in the code calling the function.
Network *do_the_thing(
Data *train_data,
Data *train_labels,
Data *x, Data *y,
size_t mini_batch_size,
int training_rate,
Network *network
) {
// same as before, but don't allocate the network
}
// Allocate space for two Networks.
// Again, there may be additional allocation and initialization required.
Network networks[2];
for(int i = 0; i < 2; i++) {
do_the_thing(
train_data,
train_labels,
x, y,
mini_batch_size,
training_rate,
&network[i] // pass in the pre-allocated memory
);
}
// No need to free, it will be done automatically.
so I'm really new at this, and I was wondering how I would go about passing a local variable in a function (in terms of the initialization). For example, I have one function (move) that declares and initializes two variables (t_row and t_column) to be used in a for loop, and within that loop, I have another functions (swap), that is called if certain conditions are met. How do I go about using those variables in the swap function. I know I need to declare them, but their initialization in the swap function depends on what iteration of the for loop swap was called. Thanks in advance for any help!
bool move(int tile)
{
for (int t_row = 0; t_row < d; t_row++)
{
for (int t_column = 0; t_column < d; t_column++)
{
if (tile == board[t_row][t_column])
{
if (0 < t_row && board[t_row - 1][t_column] == 0)
{
swap(t_row - 1, t_column);
return true;
}
}
}
}
return false;
}
void swap(int row_new, int column_new)
{
int t_row;
int t_column;
int hold = board[t_row][t_column];
board[t_row][t_column] = 0;
board[row_new][column_new] = hold;
}
The easiest way I can see to do this would be to pass in the values of the old row and column.
void swap(int row_new, int col_new, int row_old, int col_old) {
int hold = board[row_old][col_old];
board[row_old][column_old] = 0;
board[row_new][column_new] = hold;
}
monthly->maxTemperature = yearData[i].high;
monthly->minTemperature = yearData[i].low;
I just can't seem to understand the logic of what the iterations will look like or how to access the proper elements in the array of data to get the proper data for each month.... without corrupting data. Thanks!
You're on the right track:
void stats(int mth, const struct Data yearData[], int size, struct Monthly* monthStats)
{
// These are used to calc averages
int highSum = 0;
int lowSum = 0;
int days = 0;
// Initialize data
monthly->maxTemperature = INT_MIN;
monthly->minTemperature = INT_MAX;
monthly->totalPrecip = 0;
for (int i = 0; i < size; ++i) {
// Only use data from given month
if (yearData[i].month == mth) {
days += 1;
if (yearData[i].high > monthly->maxTemperature) monthly->maxTemperature = yearData[i].high;
if (yearData[i].low < monthly->minTemperature) monthly->minTemperature = yearData[i].low;
highSum += yearData[i].high;
lowSum + yearData[i].low;
monthly->totalPrecip += yearData[i].precip;
}
}
if (0 != days) {
monthly->avgHigh = highSum / days;
monthly->avgLow = lowSum / days;
}
}
Before working on the assignment it's a good idea to examine the API that you need to implement for clues. First thing to notice is that the reason the struct Monthly is passed to your function by pointer is so that you could set the result into it. This is different from the reason for passing struct Data as a pointer*, which is to pass an array using the only mechanism for passing arrays available in C. const qualifier is a strong indication that you must not be trying to modify anything off of the yearData, only the monthStats.
This tells you what to do with the min, max, average, and total that you are going to find in your function: these need to be assigned to fields of monthStats, like this:
monthStats->maxTemperature = maxTemperature;
monthStats->minTemperature = minTemperature;
...
where maxTemperature, minTemperature, and so on are local variables that you declare before entering the for loop.
As far as the for loop goes, your problem is that you ignore the mth variable completely. You need to use its value to decide if an element of yearData should be considered for your computations or not. The simplest way is to add an if to your for loop:
int maxTemperature = INT_MIN; // you need to include <limits.h>
int minTemperature = INT_MAX; // to get definitions of INT_MIN and INT_MAX
for(int i = 0; i<size; ++i) {
if (yearData[i].month < mth) continue;
if (yearData[i].month > mth) break;
... // Do your computations here
}
* Even though it looks like an array, it is still passed as a pointer
Hello guys i have threefunctions for which i get 4 warnings...!!
The first one is this
void evaluatearxikos(void)
{
int mem;
int i;
double x[NVARS+1];
FILE *controlpointsarxika;
controlpointsarxika = fopen("controlpointsarxika.txt","r");
remove("save.txt");
for(mem = 0; mem < POPSIZE; mem++)
{
for(i = 0; i < NVARS; i++)
{
x[i+1] = population[mem].gene[i];
}
rbsplinearxiki();
XfoilCall();
population[mem].fitness = FileRead();
remove("save.txt");
}
fclose(controlpointsarxika);
}
For this one the compiler warns me tha variable x is set but not used...!! But actually i am using the variable x...!!!
The second function is this one...
void elitist(void)
{
int i;
double best,worst;
int best_mem,worst_mem;
best = population[0].fitness;
worst = population[0].fitness;
for(i = 0; i < POPSIZE - 1; i++)
{
if(population[i].fitness > population[i+1].fitness)
{
if(population[i].fitness >= best)
{
best = population[i].fitness;
best_mem = i;
}
if(population[i+1].fitness <= worst)
{
worst = population[i+1].fitness;
worst_mem = i+1;
}
}
else
{
if(population[i].fitness <= worst)
{
worst = population[i].fitness;
worst_mem = i;
}
if(population[i+1].fitness >= best)
{
best = population[i+1].fitness;
best_mem = i+1;
}
}
}
if(best >= population[POPSIZE].fitness)
{
for(i = 0; i < NVARS; i++)
{
population[POPSIZE].gene[i] = population[best_mem].gene[i];
}
population[POPSIZE].fitness = population[best_mem].fitness;
}
else
{
for(i = 0; i < NVARS; i++)
{
population[worst_mem].gene[i] = population[POPSIZE].gene[i];
}
population[worst_mem].fitness = population[POPSIZE].fitness;
}
}
For this one i get two warnings that the variables worst_mem and best_mem may be used uninitialized in this function..!! But i initialize values to both of them..!!
And the third function is this...
void crossover(void)
{
int mem,one;
int first = 0;
double x;
for(mem =0; mem < POPSIZE; mem++)
{
x = rand()%1000/1000;
if(x < PXOVER)
{
first++;
if(first%2 == 0)
{
random_Xover(one,mem);
}
else
{
one = mem;
}
}
}
}
For which i get that the variable one may be used unitialized..!! But it is initialized..!
Can you please tell me what is wrong with these functions...??
Thank you in advance
In your first function, you set (assign) x, but you never read it, hence you are not using it... you're only wasting CPU cycles by writing to it. (Note also that because you index it as i+1 you write beyond the space you've allocated for it).
In the second function, your initializations to those variables are in conditional blocks. You can see that (perhaps? I didn't verify) in all conditions they are initialized but your compiler isn't that smart.
In your third function, it does appear that one could be refered to without having first been initialized.
First: You set x but do not use it. It's a local variable that gets set but it's dropped as soon as the function returns.
Second: There might be values that makes it so that your best_mem/worst_mem never gets set in your if/else, but you are using them later on. If they haven't been set, they contain garbage if not initialized.
Third: While it shouldn't happen that you try to use an uninitialized variable in your code, it still looks weird and compiler doesn't see that it won't happen first time.
When you get compiler warnings, treat is as you are doing something wrong or rather not recommended and that it could be done in a better way.
The x variable is only used on the left hand side (i.e. assigned a value). You are not using that value on the right hand side or pass it to a function.
It may be possible to get to the end of the loop for(i = 0; i < POPSIZE - 1; i++) without those variables given a value. Why not set them in the declaration.
The call to random_Xover(one,mem); could be called when one is not set. Change the line int mem,one; to int mem,one = <some value>;
I have what I consider a really strange problem. I have a function with the following prototype:
void generateNodes(const int maxX, const int maxY, node nodes[]);
As one of the first things in this function I define a 2d array of shorts, which i use as boolean values. But when I call this function the value of maxY changes to a large value. The code in question is below:
void generateNodes(const int maxX, const int maxY, node nodes[]){
int i, currentX, currentY;
short used[MAX_NODES][MAX_NODES];
//Generate the nodes
for(i = 0; i < MAX_NODES; i++){
currentX = randomNumber(0,maxX);
currentY = randomNumber(0,maxY);
nodes[i].color = 0;
nodes[i].numberOfConnections = 0;
nodes[i].id = i;
nodes[i].distanceFromStart = NOT_SET;
nodes[i].parent = NULL;
if(!used[currentX][currentY]){
nodes[i].x = currentX;
nodes[i].y = currentY;
used[currentX][currentY] = 1;
} else {
i--;
}
}
int numberOfConnections, j, currentNeighbor;
//Generate the connections
for(i = 0; i < MAX_NODES; i++){
numberOfConnections = randomNumber(1,5); //Between one and five outgoing connections
for(j = 0; j < numberOfConnections; j++){
currentNeighbor = randomNumber(0,19); //Select the neighbor
while(currentNeighbor == i){
currentNeighbor = randomNumber(0,19); //Try again while the selected is self
}
nodes[i].canReach[++(nodes[i].numberOfConnections)] = &nodes[currentNeighbor];
nodes[currentNeighbor].canReach[++(nodes[currentNeighbor].numberOfConnections)] = &nodes[i];
}
}
}
MAX_NODES is defined to 20.
Does anyone know why this might happen?
Very probably the code in ... is accessing beyond the end of used, causing arguments to be smashed. Without the code, it's of course impossible to say.
Since you do not seem to initialize the array used, it may well be that some elements are considered used (!= 0), since an array on stack is not initialized to zero, but takes whatever was in that memory area before.
An if an X,Y pair is considered used, you decrement the loop counter, possibly beyond zero into the negative realm, possibly overwriting - on the next iteration - part of the stack. This may also change the parameters, since they also reside on the same stack, before the local array.
Start with initializing used, and consider rewriting the loop to not change the loop variable except in the for statement.