How to stop recursion after some time in C - c

I need to stop recursion after, let's say, 30 seconds in C. One of my attempts was using a goto - despite recommendations of not using it, but i can't use it between different functions. The code is below:
void func_t(int n, int a, int b, int c, int d, int e, int f, int g, int height, Data *data, time_t start_time){
int cont;
data->level_recursions[height] = data->level_recursions[height] + 1;
if ( n<= 1) return;
for (cont = 1; cont <= a; cont++){
data->height = height + 1;
func_t( (n/b) - c, a, b, c, d, e, f, g, 1 + height, data );
}
for (cont = 1; cont <= d; cont++) {
data->height = height + 1;
func_t( (n/e) - f, a, b, c, d, e, f, g, 1 + height, data );
}
clock_t begin = clock();
for (cont = 1; cont <= fn(n, g); cont++);
clock_t end = clock();
data->level_work[height] = data->level_work[height] + ((double)(end - begin) / CLOCKS_PER_SEC);
}

Create a global const parameter(current time) that you init for the first running time.
If 30 sec + the value of the global < current time -> hit return or do what ever you want)
Maybe this is the if statement to enter to the recursion

Related

use snprintf in printing integer values

The code below is converting a number of seconds to the DD:HH:MM format. Instead of using printf, I would like to use snprintf. How should I print those d,h,m in the snprintf?
#include <stdio.h>
#define LONGEST 60
int main() {
int sec, h, m, s, d, temp;
char *temp_str;
int test= 2835656;
d = test / 86400; //divide the number of seconds by the number of seconds in a day
if (d < 100) {
temp = test % 86400;
temp /= 60; //
h = temp / 60; //to get "minute"
m = temp % 60; //to get "second"
} else {
d = 99;
h = 23;
m = 59;
}
printf("DD:HH:MM:%d:%d:%d\n", d, h, m); //output is DD:HH:MM:32:19:40
return 0;
}
I tried snprintf(temp_str, LONGEST, "%02s:%02s:%02s", d, h, m); but it didn't work
Why the different format string for the snprintf attempt? Just do it like you did in the printf call:
snprintf(temp_str, LONGEST, "DD:HH:MM:%d:%d:%d", d, h, m);
The %02s specifier doesn't work for integers. You also haven't declared temp_str, so you need to do that beforehand:
char temp_str[LONGEST];
After calling snprintf, the string "DD:HH:MM:32:19:40" is stored in temp_str and you can verify that with puts(temp_str);, for instance.
You must define temp_str as an array of char with at least LONGEST elements, andd you can use the same format string as for printf.
Note however that your format string should be "%02d:%02d:%02d" to produce 2 digits for each field even for values below 10.
Here is a modified version:
#include <stdio.h>
#define LONGEST 60
int main() {
int sec, h, m, s, d, temp;
char temp_str[LONGEST];
int test = 2835656;
d = test / 86400; //divide the number of seconds by the number of seconds in a day
if (d < 100) {
temp = test % 86400;
temp /= 60; // discard the seconds
h = temp / 60; // to get "hour"
m = temp % 60; // to get "minute"
} else {
d = 99;
h = 23;
m = 59;
}
snprintf(temp_str, LONGEST, "DD:HH:MM:%02d:%02d:%02d\n", d, h, m); //output is DD:HH:MM:32:19:40
fputs(temp_str, stdout);
return 0;
}

Parallelizing function using OpenMP and C

I'm trying to convert the function "integrate_openMP", which implements the trapezoid rule, so that it can be run in parallel. I'm in doubt as to which parts of the function should be governed by the "Critical" pragma and how to deal with the calculation itself regarding OpenMP.
The function is called with the pragma's
#pragma omp parallel and #pragma omp single from main.
Thank you
I have updated the code with my initial attempt to parallelize the function
double integrate_openMP(double a, double b, double (*f)(double), double e)
{
calls++;
double int_result;
double m = (a + b) / 2;
double one_trap_area = (b - a) * (f(a) + f(b)) / 2;
double two_trap_area = (b - a) * (f(a) + f(b) + 2 * f(m)) / 4;
if (fabs(one_trap_area - two_trap_area) <= e)
{
return two_trap_area;
}
else
{
double left_area, right_area;
#pragma omp task shared(left_area)
{
left_area = integrate_openMP(a, m, f, e / 2);
}
#pragma omp task shared(right_area)
{
right_area = integrate_openMP(m, b, f, e / 2);
}
#pragma omp taskwait
int_result = left_area + right_area;
return int_result;
}
}
double integrate_single(double a, double b, double (*f) (double), double e) {
calls ++;
double m = (a + b) / 2;
double one_trap_area = (b - a) * (f(a) + f(b)) / 2;
double two_trap_area = (b - a) * (f(a) + f(b) + 2 * f(m))/ 4;
if (fabs(one_trap_area - two_trap_area) <= e) {
return two_trap_area;
} else {
double left_area, right_area;
left_area = integrate_single(a, m, f, e/2);
right_area = integrate_single(m, b, f, e/2);
return left_area + right_area;
}
}
Ask yourself a few questions... "Is this loop parallleism?" in which case omp for is useful. "Is this recursive parallelism?" in which case go read up on openmp tasks...

Golden Section Method in C

I am pretty new to coding and I have been having an impossible time trying to find online help writing a C code that will use the golden section method (which apparently the GNU Scientific Library has, although I haven't had any luck finding it) to find the minimum of functions that Newton's method of minimization fails for.
Specifically I want to input an x-value as a starting point and have the code output the function's minimum value and the x coordinate of the minimum value point. My function is f(x) = x20. I am also allowed some error (< 10-3).
I don't even know where to begin with this, I have been ALL over the internet and haven't found anything helpful. I would seriously appreciate some help as to where I might find more information, or how I might implement this method.
Edit:
This is my code as of now:
#include <gsl/gsl_errno.h> /* Defines GSL_SUCCESS, etc. */
#include <gsl/gsl_math.h>
#include <gsl/gsl_min.h>
int minimize_convex(gsl_function *F,double a, double b, double *x_min, double tol)
{
int status;
double h = (b - a) * .0000001; /* Used to test slope at boundaries */
/* First deal with the special cases */
if (b - a < tol)
{
*x_min = b;
status = GSL_SUCCESS;
}
/* If the min is at a, then the derivative at a is >= 0. Test for
* this case. */
else if (GSL_FN_EVAL(F, a + h) - GSL_FN_EVAL(F, a) >= 0)
{
*x_min = a;
status = GSL_SUCCESS;
}
/* If the min is at b, then the derivative at b is >= 0. Test for
* this case. */
else if (GSL_FN_EVAL(F, b - h) - GSL_FN_EVAL(F, b) >= 0)
{
*x_min = b;
status = GSL_SUCCESS;
}
else
{
/* Choose x_guess so that it's value is less than either of the two
* endpoint values. Since we've got this far, we know that at least
* of of F(a + h) and F(b - h) has this property. */
double x_guess;
x_guess = (GSL_FN_EVAL(F, a + h) < GSL_FN_EVAL(F, b - h)) ?
a + h : b - h;
int iter = 0, max_iter = 200;
const gsl_min_fminimizer_type *T;
gsl_min_fminimizer *s;
T = gsl_min_fminimizer_goldensection;
s = gsl_min_fminimizer_alloc(T);
gsl_min_fminimizer_set(s, F, x_guess, a, b);
do
{
iter++;
status = gsl_min_fminimizer_iterate(s); /* perform iteration */
status =
gsl_min_test_interval(a, b, tol, 0.0); /* |a - b| < tol? */
a = gsl_min_fminimizer_x_lower(s);
b = gsl_min_fminimizer_x_upper(s);
if (status == GSL_SUCCESS)
{
*x_min = gsl_min_fminimizer_x_minimum(s); /* current est */
}
}
while (status == GSL_CONTINUE && iter < max_iter);
gsl_min_fminimizer_free(s);
}
return status;
}
double f(double x, void *params)
{
double *p = (double *) params;
return (x^(50)) + *p;
}
double C = 0.0;
int main (void)
{
double m = 0.0, result;
double a = -1.0, b = 1.0;
double epsilon = 0.001;
int exit_val;
gsl_function F;
F.function = &f;
F.params = &C;
exit_val = minimize_convex(&F, a, b, m, &result, epsilon);
printf("Minimizer: %g\n", result);
printf("Function value: %g\n", f(result, &C));
printf("%d\n", exit_val);
return 0;
}
I am getting the following errors:
try.c:69:14: error: invalid operands to binary
expression ('double' and 'double')
return (x^(50)) + *p;
try.c:81:54: error: too many arguments to function
call, expected 5, have 6
exit_val = minimize_convex(&F, a, b, m, &result, epsilon);
Any thoughts?
gsl has a generic minimizer that can use multiple methods to acheive the minimization. The description of how to use the minimizer can be found in the documentation. You can set it to the golden section method by delcaring the method as gsl_min_fminimizer_goldensection.

Any reason why a loop wouldn't terminate even with an 'i' limiting value of repeats?

I'm doing this assignment for college in C, should be fairly simple, but a loop in it doesn't seem to terminate so the code won't work properly; even if I put in an i value to limit the amount of times it loops. Tried it with a for loop too, still gets stuck.
The code is supposed to take in values of coefficients and try to work out a root for a cubic equation by finding the midpoint between two large values and trying that out to see if it gets 0, if it doesn't, it should change one of the limits to the midpoint value. Here's the relevant code:
int main (void)
{
int i, u=1000, l=-1000;
float a, b, c, d, mid, y;
scanf(" %f %f %f %f", &a, &b, &c, &d);
while (abs(u - l) > 0.001 && i < 10)
{
mid= (u + l)/2;
y = a * pow(mid, 3) + b* pow(mid, 2) + c * mid + d;
if(y == 0) break;
else if(y < 0) l = mid;
else u = mid;
i++;
}
printf("\nThere is a root at: x = %.3f\n", mid);
}
Any help would be appreciated, thanks!
edit: Oh my god I'm an idiot. Always the small things. The code still isn't working but at least it's not stuck anymore, thanks guys!
You declared i, but did not initialize it, so it is set to whatever random value was left in memory.
For this example, lets say that value was -12,345.
Then i can be incremented over 12,000 times before it is greater than 10!
Your loop will run when i is incremented 12,355 times, and its value becomes 10, and the test i < 10 finally fails.
To fix this, initialize i = 0:
int i=0;
2 things. Initialize i to 0. this will ensure it terminates after 10 loops.
More important for your problem though, you have declared u and l as integers, I think you need to declare them as floats.
You need to initialize i: int i = 0;
This should work for you! You need to initialize i.
#include <stdio.h>
#include <math.h>
int main (void)
{
int i = 0, u = 1000, l =- 1000;
float a, b, c, d, mid, y;
scanf(" %f %f %f %f", &a, &b, &c, &d);
while (abs(u-l)>0.001 && i<10)
{
mid = (u + l)/2;
y = a*pow(mid,3) + b* pow(mid,2) + c*mid + d;
if(y == 0)
break;
else if(y<0)
l = mid;
else
u = mid;
i++;
}
printf("\nThere is a root at: x = %.3f\n", mid);
}
If you make u and l be floats then your while-loop terminates without i. Before that, abs(u-l) where u-l are ints will only terminate if a root is at zero. You also need to use fabs() instead of abs():
int main (void)
{
float u=1000.0, l=-1000.0;
float a, b, c, d, mid, y;
scanf(" %f %f %f %f", &a, &b, &c, &d);
while (fabs(u - l) > 0.001)
{
mid= (u + l)/2.0;
y = a * pow(mid, 3) + b* pow(mid, 2) + c * mid + d;
if(y == 0) break;
else if(y < 0) l = mid;
else u = mid;
}
printf("\nThere is a root at: x = %.3f\n", mid);
}
Seems like you still have something wrong in the bisection algorithm condition when you reset l and u to mid. I'm attaching a fixed version, and I used different variable names (sorry) to keep my head clear:
#define NMAX 1000
#define TOL 0.00001
int sign( float x ) {
if (x > 0.0) return 1;
if (x < 0.0) return -1;
return 0;
}
int main (void)
{
int n=0;
float fa, fc, b=1000.0, a=-1000.0;
float p3,p2,p1,p0,c;
scanf(" %f %f %f %f", &p3, &p2, &p1, &p0);
while(n<NMAX)
{
c = (a + b)/2.0;
fc = p3*pow(c, 3) + p2*pow(c, 2) + p1*c + p0;
if(fc == 0.0 || (b-a)/2.0 < TOL ) break;
fa = p3*pow(a, 3) + p2*pow(a, 2) + p1*a + p0;
if( sign(fc) == sign(fa) )
a = c;
else
b = c;
n++;
}
if(n==NMAX) {
printf("Method failed.\n");
}
else {
printf("\nThere is a root at: x = %.3f\n", c);
}
}

Get stuck in a loop while returning multiple arrays from a local function?

I have to find the minimum and maximum angle of a catapult's trajectory that will make it over a wall. I have a local function that includes the motion equations and returns the distance at which the object lands, an array of x values, an array of y values, and the number of x and y values based on an input of lots of conditions called anglesfunction. In the main function, I tried to call it multiple times in a loop but it must be an infinite loop because I have to quit the program. It always quits on the same line, which is:
[temp(p), a, b, c(p)] = anglefunction(v0, w, m, d, h, dw, theta2(p), k);
I have it commented out right now, but I tried to do a similar thing later to do bisection and it stops at the same point there too. Here's my full code, g is gravity and is the only thing I am passing in to the main function.
function [mid] = longassignment3(g)
v0 = 40;
w = 5;
m = 10;
d = 50;
h = 5;
dw = 30;
theta1 = 38;
k = .05;
n = 1;
%hold on
%grid on
A = 0:.01:h;
%plot(dw, A, 'r', 'linewidth',2)
%plot(d, 0, 'linewidth', 2)
[distance, x, y, z] = anglefunction(v0, w, m, d, h, dw, theta1, k); %should take out eventually
%plot(x,y);
min = 0;
max = 0;
q = 1;
tol = .3;
tester = 2;
theta2 = 0:.01:90;
p = 1;
dt = 1e-3;
num = 1;
[temp(p), a, b, c(p)] = anglefunction(v0, w, m, d, h, dw, theta2(p), k); %for p=1
while theta2(p) < 90
p = p + 1; %p becomes 2
[temp(p), a, b, c(p)] = anglefunction(v0, w, m, d, h, dw, theta2(p), k); %for p=2 the first time
B = size(a);
while q <= B(2);
if a(q) >= dw & a(q) <= (dw+tol)
num = q;
end
q = q + 1;
end
if b(num) >= (h - tol) || b(num) <= (h+tol) %if it hits wall
min = 0;
max = 0;
else %does not hit the wall
if temp(p)<temp(p-1)
min = theta2(p); %not assigning max and min
elseif temp(p)>temp(p-1)
max = theta2(p);
end
end
end
%min
%max
%distance = 0;
%q = 1;
%min = 26;
%max = 45;
%u = 1;
%done = 1;
%while done ~= 0
% total = min + max;
% mid = total/2;
% [distance(u), a, b, c(u)] = anglefunction(v0, w, m, d, h, dw, mid, k);
% if distance(u) < d
% max = mid;
% elseif distance(u) > d
% min = mid;
% elseif distance(u) >= d-tol | distance(u) <= d+tol
% done = 0;
% end
% u = u + 1;
%end
end
if true
function [dist, x, y, n] = anglefunction(v0, w, m, d, h, dw, theta1, k)
n = 1;
g = 9.81;
%hold on
%grid on
A = 0:.01:h;
clear vx vy x y
%plot(dw, A, 'r', 'linewidth',2)
%plot(d, 0, 'linewidth', 2)
x(n) = 0;
y(n) = 0;
dvx = 0;
dvy = 0;
dt = 1e-3;
vx(n) = (v0)*(cos(theta1*pi/180));
vy(n) = (v0)*(sin(theta1*pi/180));
while y(n)>=0 && x(n)>=0
veff(n) = sqrt((vx(n) - w)^2 + (vy(n))^2);
dvx(n) = -k*veff(n)*(vx(n) - w)*dt/m;
dvy(n) = (-k*veff(n)*vy(n)/m-g)*dt;
vx(n+1) = vx(n) + (dvx(n));
vy(n+1) = vy(n) + (dvy(n));
x(n+1) = x(n) + (vx(n))*dt;
y(n+1) = y(n) + (vy(n))*dt;
n = n +1 ;
end
dist = x(n);
end
In the commented out while loop, max & min both become equal to 45 after a couple of iterations. This makes 'mid' equal to 45 as well, and so there is no change in the parameters you're passing into anglefunction each iteration. Therefore, there's no way that the 'done=0' condition can be reached and the while loop goes on forever.

Resources