Finding minimum of a function with N variables - c

I'm trying to code an algorithm to locate the minimum of Rosenbrock function that may have N variables. When N = 2, I can easily figure it out. The code that I'm using for N = 2 is below:
double y,z,x, aux1, aux2;
double menor = INT_MAX;
y = INT_MIN;
x = INT_MIN;
while(x < INT_MAX)
{
while(y < INT_MAX)
{
z = (1-x)*(1-x) + 100*(y - (x*x))*(y - (x*x));
if(menor > z)
{
menor = z;
aux1 = x;
aux2 = y;
}
y = y + 0.1;
}
y = 0.1;
x = x + 0.1;
}
printf("(x,y) : (%.2lf, %.2lf) Minimum value of z: %.2lf\n", aux1, aux2, menor);
This code is working fine and I'm summing y and x by 0.1 only because I already know what the minimum is given that function (it's on (1,1)). It takes a little while to run, but it works. My problem is for N variable. When I think about this, what comes to my mind is that I will need N repetition structures. Here is the code as it's by now. Its not working, but it may give some idea of what I'm trying to do:
//Calculates the value of the Rosenbrock function given n(the number of variables)
double rosen(double *x, int n){
double y;
for(int i = 0; i < n-1; i++)
{
y = y + 100*((x[i+1] - x[i]*x[i])*(x[i+1] - x[i]*x[i])) + (1 - x[i])*(1 - x[i]);
}
return y;
}
int main(void){
double *x;
//n is the number of variables and it may change
int n = 3;
x = (double*)malloc(n * sizeof(double));
double rosen(double *x, int n);
for(int i = 0; i < n; i++)
{
x[i] = INT_MIN;
}
//That's the part where I can't figure out how to compute all the possibilities, changing the value of the last variable between INT_MIN AND INT_MAX. Then this variable gets the value of INT_MIN again and I will sum 0.1 to the variable antecedent, and then do all the process again to the last variable. And so on for all the N variables.
for(int i = n - 1; i >= 0; i--)
{
while(x[i] < INT_MAX)
{
x[i] = x[i] + 0.1;
}
x[i] = INT_MIN;
}
This code above probably contain some erros. But, the only thing I'm needing help is to vary all the values of the N variables. So, what I want to do is take the last variable and vary its value between INT_MIN and INT_MAX, summing 0.1(I know its really a long journey). After that, this variable will receive INT_MIN value again and the antecedent variable will vary by +0.1. Then, the last variable will vary from INT_MIN to INT_MAX again. And this will happen for all the N variables.
This is a problem that I'm trying to solve, to brute-force the value of a function to get its minimum. If you guys have some tips for me or some library that may help, I will be very gratefull.

You can have a recursive function like the following (rough C):
void rosenMin(int maxDims, int currDim, double[] values, double* currMin)
{
if (currDims == maxDims) {
double rosenVal = rosen(values); // You need to implement this
if (rosenVal < *currMax) {
*currMin = rosenVal;
}
} else {
for (double c = INT_MIN; c <= INT_MAX; c += 0.1) {
values[currDim + 1] = c;
rosenMin(maxDim, currDim + 1, values, currMin);
}
}
}
double[] values = new double[N] { 0 }; // Check with C syntax how this'll look!
double min = INT_MAX
rosenMin(N, 1, values, &min);

Related

Find k out of n subset with maximal area

I have n points and have to find the maximum united area between k points (k <= n). So, its the sum of those points area minus the common area between them.
]1
Suppose we have n=4, k=2. As illustrated in the image above, the areas are calculated from each point to the origin and, the final area is the sum of the B area with the D are (only counting the area of their intersection once). No point is dominated
I have implemented a bottom-up dynamic programming algorithm, but it has an error somewhere. Here is the code, that prints out the best result:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct point {
double x, y;
} point;
struct point *point_ptr;
int n, k;
point points_array[1201];
point result_points[1201];
void qsort(void *base, size_t nitems, size_t size,
int (*compar)(const void *, const void *));
int cmpfunc(const void *a, const void *b) {
point *order_a = (point *)a;
point *order_b = (point *)b;
if (order_a->x > order_b->x) {
return 1;
}
return -1;
}
double max(double a, double b) {
if (a > b) {
return a;
}
return b;
}
double getSingleArea(point p) {
return p.x * p.y;
}
double getCommonAreaX(point biggest_x, point new_point) {
double new_x;
new_x = new_point.x - biggest_x.x;
return new_x * new_point.y;
}
double algo() {
double T[k][n], value;
int i, j, d;
for (i = 0; i < n; i++) {
T[0][i] = getSingleArea(points_array[i]);
}
for (j = 0; j < k; j++) {
T[j][0] = getSingleArea(points_array[0]);
}
for (i = 1; i < k; i++) {
for (j = 1; j < n; j++) {
for (d = 0; d < j; d++) {
value = getCommonAreaX(points_array[j - 1], points_array[j]);
T[i][j] = max(T[i - 1][j], value + T[i - 1][d]);
}
}
}
return T[k - 1][n - 1];
}
void read_input() {
int i;
fscanf(stdin, "%d %d\n", &n, &k);
for (i = 0; i < n; i++) {
fscanf(stdin, "%lf %lf\n", &points_array[i].x, &points_array[i].y);
}
}
int main() {
read_input();
qsort(points_array, n, sizeof(point), cmpfunc);
printf("%.12lf\n", algo());
return 0;
}
with the input:
5 3
0.376508963445 0.437693410334
0.948798695015 0.352125307881
0.176318878234 0.493630156084
0.029394902328 0.951299438575
0.235041868262 0.438197791997
where the first number equals n, the second k and the following lines the x and y coordinates of every point respectively, the result should be: 0.381410589193,
whereas mine is 0.366431740966. So I am missing a point?
This is a neat little problem, thanks for posting! In the remainder, I'm going to assume no point is dominated, that is, there are no points c such that there exists a point d with c.x < d.x and c.y < d.y. If there are, then it is never optimal to use c (why?), so we can safely ignore any dominated points. None of your example points are dominated.
Your problem exhibits optimal substructure: once we have decided which item is to be included in the first iteration, we have the same problem again with k - 1, and n - 1 (we remove the selected item from the set of allowed points). Of course the pay-off depends on the set we choose - we do not want to count areas twice.
I propose we pre-sort all point by their x-value, in increasing order. This ensures the value of a selection of points can be computed as piece-wise areas. I'll illustrate with an example: suppose we have three points, (x1, y1), ..., (x3, y3) with values (2, 3), (3, 1), (4, .5). Then the total area covered by these points is (4 - 3) * .5 + (3 - 2) * 1 + (2 - 0) * 3. I hope it makes sense in a graph:
By our assumption that there are no dominated points, we will always have such a weakly decreasing figure. Thus, pre-sorting solves the entire problem of "counting areas twice"!
Let us turn this into a dynamic programming algorithm. Consider a set of n points, labelled {p_1, p_2, ..., p_n}. Let d[k][m] be the maximum area of a subset of size k + 1 where the (k + 1)-th point in the subset is point p_m. Clearly, m cannot be chosen as the (k + 1)-th point if m < k + 1, since then we would have a subset of size less than k + 1, which is never optimal. We have the following recursion,
d[k][m] = max {d[k - 1][l] + (p_m.x - p_l.x) * p_m.y, for all k <= l < m}.
The initial cases where k = 1 are the rectangular areas of each point. The initial cases together with the updating equation suffice to solve the problem. I estimate the following code as O(n^2 * k). The term squared in n can probably be lowered as well, as we have an ordered collection and might be able to apply a binary search to find the best subset in log n time, reducing n^2 to n log n. I leave this to you.
In the code, I have re-used my notation above where possible. It is a bit terse, but hopefully clear with the explanation given.
#include <stdio.h>
typedef struct point
{
double x;
double y;
} point_t;
double maxAreaSubset(point_t const *points, size_t numPoints, size_t subsetSize)
{
// This should probably be heap allocated in your program.
double d[subsetSize][numPoints];
for (size_t m = 0; m != numPoints; ++m)
d[0][m] = points[m].x * points[m].y;
for (size_t k = 1; k != subsetSize; ++k)
for (size_t m = k; m != numPoints; ++m)
for (size_t l = k - 1; l != m; ++l)
{
point_t const curr = points[m];
point_t const prev = points[l];
double const area = d[k - 1][l] + (curr.x - prev.x) * curr.y;
if (area > d[k][m]) // is a better subset
d[k][m] = area;
}
// The maximum area subset is now one of the subsets on the last row.
double result = 0.;
for (size_t m = subsetSize; m != numPoints; ++m)
if (d[subsetSize - 1][m] > result)
result = d[subsetSize - 1][m];
return result;
}
int main()
{
// I assume these are entered in sorted order, as explained in the answer.
point_t const points[5] = {
{0.029394902328, 0.951299438575},
{0.176318878234, 0.493630156084},
{0.235041868262, 0.438197791997},
{0.376508963445, 0.437693410334},
{0.948798695015, 0.352125307881},
};
printf("%f\n", maxAreaSubset(points, 5, 3));
}
Using the example data you've provided, I find an optimal result of 0.381411, as desired.
From what I can tell, you and I both use the same method to calculate the area, as well as the overall concept, but my code seems to be returning a correct result. Perhaps reviewing it can help you find a discrepancy.
JavaScript code:
function f(pts, k){
// Sort the points by x
pts.sort(([a1, b1], [a2, b2]) => a1 - a2);
const n = pts.length;
let best = 0;
// m[k][j] represents the optimal
// value if the jth point is chosen
// as rightmost for k points
let m = new Array(k + 1);
// Initialise m
for (let i=1; i<=k; i++)
m[i] = new Array(n);
for (let i=0; i<n; i++)
m[1][i] = pts[i][0] * pts[i][1];
// Build the table
for (let i=2; i<=k; i++){
for (let j=i-1; j<n; j++){
m[i][j] = 0;
for (let jj=j-1; jj>=i-2; jj--){
const area = (pts[j][0] - pts[jj][0]) * pts[j][1];
m[i][j] = Math.max(m[i][j], area + m[i-1][jj]);
}
best = Math.max(best, m[i][j]);
}
}
return best;
}
var pts = [
[0.376508963445, 0.437693410334],
[0.948798695015, 0.352125307881],
[0.176318878234, 0.493630156084],
[0.029394902328, 0.951299438575],
[0.235041868262, 0.438197791997]
];
var k = 3;
console.log(f(pts, k));

Fractions: Sum and difference in C programming

I'm facing problems in writing a program in C that calculates S, being S = {1/50 - 3/48 + 5/46...} with 9 elements. I don't know how to use the DIFFERENCE operator followed by a SUM operator, and I MUST use the for structure.
Here's the program I wrote:
#include <stdio.h>
#include <stdlib.h>
int main (void) {
int n, d, S, i;
i = 0;
n = 1;
d = 50;
S = n / ((double)d);
for (i = 0; i < 4; i++) {
n += 2;
n -= 2;
S = S + (n / ((double)d));
S = S - (n / ((double)d));
}
printf("%d", S);
return 0;
}
I know that the variable declarations may be wrong and that's exactly where I get confused. I decalred S as an integer but put d (denominator) to double 'cause the result must be a decimal number, of course.
Can anybody help me??
The output I'm getting is: 0
Perhaps like this. The most important point, is to use the double type, because the int type can only hold whole numbers.
#include <stdio.h>
int main (void) {
int i;
double sign = 1.0; // sign
double num = 1.0; // numerator
double div = 50.0; // divisor
double sum = 0.0; // series sum
for (i = 0; i < 9; i++) {
sum += sign * num / div; // accumulate the term
num += 2.0; // numerator +2
div -= 2.0; // divisor -2
sign *= -1.0; // alternate the sign
printf("%f\n", sum); // show double result
}
return 0;
}
Program output:
0.020000
-0.042500
0.066196
-0.092895
0.121390
-0.153610
0.188496
-0.228171
0.271829
Different things to say about your code.
First you cannot use an integer for your sum since you want a floating point result.
Then as mentioned in comments you are using successive operations that result in not changing the variable
n+=2; n-=2;
You could simply do something like :
double S = 0.0; int N=9;
for(i=0; i < N; ++i) {
S += ( (i % 2 == 0)?(1.0):(-1.0) ) * (2.0*i+1)/(50-(2.0*i+1));
}
The instruction (i % 2 == 0)?(1.0):(-1.0) pick 1 if 'i' is even and -1 if 'i' is odd.
Finally if S is no longer an int you must change your printf with a floating point format like for example '%f'.
Check if what you're looking for is the following code:
#include <stdio.h>
#include <stdlib.h>
void main () {
int n = 1, d = 50, i = 0, signal = 1;
double S = n / (double) d;
for (i = 0; i < 8; i++) {
n += 2;
d -= 2;
signal = -signal;
S += signal * n/(double)d;
}
printf("%f", S);
}
I think you're missing S is a double number. int/double = double, but youre assign this math in a int variable.

|c| Series 1+2x+3x^2+4x^3+....nx^(n-1)

First of all, I searched and all questions I found are similar but not exactly this one.
This is my first post here, I'm a beginner in programming and currently learning to code in C.
Been struggling with this code for about 5 hours now.
The question is create a program in C, using only loops (and not using pow(), using stdio.h library only).
The question is to get the user to give you two numbers - X and N
the program will print The result of the following equation:
1+2x+3x^2+4x^3+....+nx^(n-1)
For example for the input of - X=2 N=3
1*2^0 + 2*2^1 + 3*2^2
What the program will print is "17"
This is my attempt so far, I got to the Power function but I cant find a way to incorporate into the programm itself.
#include <stdio.h>
int main(void)
{
int i, j=0, b = 0;
float x, n;
double sum = 0, sumt=0;
do{
printf("Please enter two numbers \n");
flushall;
scanf("%f %f", &n, &x);
} while (x <= 0);
for (i = 1; i <= n; i++){
sum = x*x;
}
sumt += sum;
printf("%f", sum);
}
Instead of trying to create an implementation of pow, you will need to take advantage of the relationship between the terms of the expression.
The n-th term is nx^(n-1). The n-1-the term is (n-1)x^(n-2).
If we denote the n-th term as T(n) and denote the n-1-th term as T(n-1),
T(n) = T(n-1)*x*n/(n-1)
Given the starting value of the first term,
T(1) = 1
you can compute the subsequent terms using the above formula.
The following code should work.
// Initialize the values for N=1
term = 1;
sum = 1;
// Iterate starting from 2
for (i = 2; i <= n; i++){
term *= x*i/(i-1);
sum += term;
}
The working Program based on the tips given by the almighty #R_Sahu (And others ;D)
**
#include <stdio.h>
int main(void)
{
int i, j = 0, c = 0;
float x, n, b = 0;
double term, sum;
do {
printf("Enter Two Numbers\n");
flushall;
scanf("%f%f", &n, &x);
} while (x < 0);
for (i = 2; i < n + 2; i++)
{
term = 1;
sum = 1;
for (i = 2; i <= n; i++){
term *= x*i / (i - 1);
sum += term;
}
}
printf("The answer is %.lf ", sum);
}
I will not give you the code, but the reasoning you should follow
First you have to somehow get the data from the user (as a parameter, from stdio... whatever)
x = getFromUser
n = getFromUser
You will then need to init a temporary result
result = 0
How many times do you have to add? -> Exactly n times
for(ii=0;ii<n;ii++) {
result = result + pow((ii*x),(ii-1)) //There is something missing here, I'll let you guess what
}
But wait; you cannot use pow. So you have to program it by yourself (I guess that's the idea of the exercise)
then you need a function, and it has to return an int (actually, it may return even irrational numbers, but I don't think they will require you to do that)
int customPow(int base, int exponent) {
//Put your for in here, and may the pow be with you
}
You need to figure out the code yourself, but the general idea is as follows:
Create your own pow function which returns x*n.
int pow(int x, int n){
//use a for or while loop to calculate x (*x)n times.
//pay attention to the base cases (i.e., when n = 0, or 1 etc)
}
ans = 0;
for(i = 0 to N-1){
ans = ans + pow(x,i-1)*i;
}

Getting an incorrect output for e^x function I made for class, and getting the wrong number of terms

So for my Intro to computer programming class we have to write 3 separate functions, one to calculate factorials, one to calculate powers (x^n), and one to calculate the number of terms of the taylor series with the given error approximation. Everytime I run my program, it prints that Nterms=1, instead of like 100, 300, 1000, etc.
It's probably a simple error in my loop, but I can't locate it. Any help is appreciated!
#include<stdio.h>
#include<math.h>
double power(float A, int B)
{
double sum=1.00;
int nterms=1;
while ( nterms <= B && B > 0)
{
sum = A*sum;
nterms++;
}
return sum;
}
double factorial(int b)
{
double fact=1.00;
while (b >= 2)
{
fact = b*(b-1)*fact;
b = b-2;
}
return fact;
}
int Terms(float X, float a)
{
int N=1,l;
double L,R;
while (L < a && a <= R)
{
l=N+1;
L= (power(X,l)/(factorial(l)));
R= (power(X,N)/(factorial(N)));
N++;
}
return N;
}
int main()
{
float x, delta;
double sum=0.00, term=0.00;
int n, Nterms;
printf("Please enter a decimal number. x=");
scanf("%f",&x);
printf("Please enter an another number. delta=");
scanf("%f",&delta);
Nterms=Terms(x,delta);
printf("Nterms=%d\n",Nterms);
for(n=0;n<Nterms;n++)
{
if( n==0 || n==1 )
{
sum = 1 + x;
}
else
{
sum = sum + term;
term = (power(x,n))/(factorial(n));
}
}
printf("The approximation for e^(%f)=%.4f",x,sum);
return 0;
}
That your Terms function always returns 1 means that N never changes from its initial value, which means that you never enter the while loop
while (L < a && a <= R)
which means that the condition is never satisfied.
I suggest stepping through, noting what you think L and R ought to be when you should require more terms, and checking what they actually are when you get there without initializing them.
I doubt this is the only problem, but your terms function should probably use a bottom tested loop so that L and R are at least defined. Also, you don't really need to test both L and R as you know L failed to meet the R criteria on the previous iteration. Something like:
int Terms(float X, float a)
{
int N=0;
double R;
do {
N++;
R = (power(X,N)/(factorial(N)));
} while (a <= R)
return N;
}

Converting an int array to an int value in c

I have an integer array
int number[] = {1,2,3,4};
What can I do to get int x = 1234?
I need to have a c version of it.
x = 1000*number[0] + 100*number[1] + 10*number[2] + number[3];
This is basically how decimal numbers work. A more general version (when you don't know how long 'number' is) would be:
int x = 0;
int base = 10;
for(int ii = 0; ii < sizeof(number); ii++) x = base*x + number[ii];
Note - if base is something other than 10, the above code will still work. Of course, if you printed out x with the usual cout<<x, you would get a confusing answer. But it might serve you at some other time. Of course you would really want to check that number[ii] is between 0 and 9, inclusive - but that's pretty much implied by your question. Still - good programming requires checking, checking, and checking. I'm sure you can add that bit yourself, though.
You can think of how to "shift over" a number to the left by multiplying by ten. You can think of appending a digit by adding after a shift.
So you effectively end up with a loop where you do total *= 10 and then total += number[i]
Of course this only works if your array is digits, if it is characters you'll want to do number[i] - '0' and if it is in a different base you'll want to multiply by a different number (8 for instance if it is octal).
int i = 0, x = 0;
for(; i < arrSize; i++)
x = x * 10 + number[i];
x is the result.
int i;
int x = 0;
for ( i = 0; i < 4; i++ )
x = ( 10 * x + number[i] );
int number[]={1,2,3,4}
int x=0,temp;
temp=10;
for(i=0;i<number.length;i++)
{
x=x*temp+number[i];
}
cout>>x;
You could do something with a for loop and powers of 10
int tens = 1;
int final = 0;
for (int i = arrSize - 1; i <= 0; ++i)
{
final += tens*number[i];
tens*=10;
}
return final;
Answer is quite easy.Just list a complete function here.
int toNumber(int number[],arraySize)
{
int i;
int value = 0;
for(i = 0;i < arraySize;i++)
{
value *=10;
value += number[i];
}
return value;
}

Resources