Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

function minimizer issue #8

Open
rvignolo opened this issue Aug 12, 2019 · 12 comments
Open

function minimizer issue #8

rvignolo opened this issue Aug 12, 2019 · 12 comments

Comments

@rvignolo
Copy link
Member

Check out this mwe:

x0 = 0.15
f(x) := sin(2 * pi * 1 * (x - x0))

# PRINT_FUNCTION f MIN 0.5 MAX 1.0 STEP 0.01 FORMAT %e
PRINT func_min(f(x),x,0.5,1.0)
PRINT func_min(f(x),x,0.5,1.0,1e-10)
PRINT func_min(f(x),x,0.5,1.0,1e-10,0)
PRINT func_min(f(x),x,0.5,1.0,1e-10,1)
PRINT func_min(f(x),x,0.5,1.0,1e-10,2)
PRINT func_min(f(x),x,0.5,1.0,1e-10,0,0)
PRINT func_min(f(x),x,0.5,1.0,1e-10,0,1)
PRINT func_min(f(x),x,0.5,1.0,1e-10,1,0)
PRINT func_min(f(x),x,0.5,1.0,1e-10,1,1)
PRINT func_min(f(x),x,0.5,1.0,1e-10,2,0)
PRINT func_min(f(x),x,0.5,1.0,1e-10,2,1)

The correct value is 0.9. However, we only reach that value when we set nocomplain = 1. What do you think about this?

@gtheler
Copy link
Contributor

gtheler commented Aug 12, 2019

This seems to be an issue with gsl_min_fminimizer_set here https://www.gnu.org/software/gsl/doc/html/min.html

That function needs three values for x: the two extrema and the guess where the minimum is. Wasora sets the guess as the average of the extrema. With those values, the function above fails with GSL_EINVAL instead of success. I do not know what it does. If you change 0.5 for 0.7 the searcher works.

I will need help from your side to figure this out...

@rvignolo
Copy link
Member Author

Ok, so the problem is that GSL believes that this function is a monotonically decreasing function, because it is evaluated at x_lower, x_upper and x = 0.5*(x_lower + x_upper). In order to find a minimum, we have to comply with the GSL requirement:

f(x_lower) > f(x) < f(x_upper)

In this particular example, this condition is not fulfilled, because f(0.5) > f(0.75) > f(1.0). When you change x_lower from 0.5 to 0.75, the problem is resolved.

So, the question is, can we estimate a better start value for the minimum?

@rvignolo
Copy link
Member Author

oh, and another thing is, why this is automatically resolved when setting nocomplain = 1? Maybe we can use that idea to solve the problem!

@gtheler
Copy link
Contributor

gtheler commented Aug 12, 2019

  1. be my guest and come up with an algorithm to modify either any of the xs to try to get with a valid range (maybe make a few iterations with random pertubations?)
  2. because even though the call to gsl_min_fminimizer_set fails, it goes ahead and apparently the algorithm works but I undertand that GSL says "it might work but it also might not work" so they fail on the safe side

@rvignolo
Copy link
Member Author

  1. Maybe the valid range should be provided by the user, but we might print a warning or an error explaining the problem, so the user fixes the search interval.

  2. Yes, that is correct. Actually, I believe that when you go ahead, GSL selects over one of the two sub intervals: [x_lower, x] or [x, x_upper]. In this case, it selects the correct one, i.e. [x, x_upper]. I have to think but I am not sure if it can select the incorrect one or if it always selects the potentially correct one.

@rvignolo
Copy link
Member Author

rvignolo commented Aug 13, 2019

For completeness, check out this input:

x0 = 0.15
f(x) := sin(2 * pi * 1 * (x - x0))

# a = 0.5
# b = 1.0

a = 0.8
b = 1.3

# PRINT_FUNCTION f MIN a MAX b STEP 0.01 FORMAT %e
PRINT func_min(f(x),x,a,b)
PRINT func_min(f(x),x,a,b,1e-10)
PRINT func_min(f(x),x,a,b,1e-10,0)
PRINT func_min(f(x),x,a,b,1e-10,1)
PRINT func_min(f(x),x,a,b,1e-10,2)
PRINT func_min(f(x),x,a,b,1e-10,0,0)
PRINT func_min(f(x),x,a,b,1e-10,0,1)
PRINT func_min(f(x),x,a,b,1e-10,1,0)
PRINT func_min(f(x),x,a,b,1e-10,1,1)
PRINT func_min(f(x),x,a,b,1e-10,2,0)
PRINT func_min(f(x),x,a,b,1e-10,2,1)

This time, GSL selects the potentially correct interval as well.

@gtheler
Copy link
Contributor

gtheler commented Aug 13, 2019

if you want, make the default behavior as nocomplain, i.e. change the flag to complain and switch the if statement

@rvignolo
Copy link
Member Author

rvignolo commented Aug 13, 2019

I am not sure about that... I have already tested that way and results can be incorrect as well. So there is virtually no advantage with respect to what we have now.

Maybe, we must catch the GSL error:

if (f_minimum >= f_lower || f_minimum >= f_upper)
    {
      GSL_ERROR ("endpoints do not enclose a minimum", GSL_EINVAL);
    }

and replace it by:

wasora_push_error_message("Interval endpoints may not enclose a minimum. Please, plot your function and make sure that the following conditions are fulfilled: f(x_lower) > f(x) and f(x) < f(x_upper), with x a first estimate of the location of the minimum.");
wasora_runtime_error();

This way, we can remove the current seventh argument nocomplain and replace the instruction for

func_min(f(x), x_lower, x_upper, x_estimate, epsrel, algorithm)

or

func_min(f(x), x_lower, x_upper, x_estimate, epsrel, algorithm, force)

with force a flag that indicates if we must force the minimum search.

Of course, the x_estimate value can be defaulted as the medium value.

Let me know what you think!

@gtheler
Copy link
Contributor

gtheler commented Aug 13, 2019

Go ahead.

@rvignolo
Copy link
Member Author

ok! I will do it now

@rvignolo
Copy link
Member Author

As I have previously explained, I want to catch the GSL error given by:

if (f_minimum >= f_lower || f_minimum >= f_upper)
    {
      GSL_ERROR ("endpoints do not enclose a minimum", GSL_EINVAL);
    }

However, when we call gsl_min_fminimizer_set, theGSL_EINVAL status can be also retrieved by two other conditions:

if (x_lower > x_upper)
    {
      GSL_ERROR ("invalid interval (lower > upper)", GSL_EINVAL);
    }

  if (x_minimum >= x_upper || x_minimum <= x_lower) 
    {
      GSL_ERROR ("x_minimum must lie inside interval (lower < x < upper)",
                 GSL_EINVAL);
    }

In this context, I cannot make the following check gsl_status == GSL_EINVAL in order to tell the user that

wasora_push_error_message("Interval endpoints may not enclose a minimum. Please, plot your function and make sure that the following conditions are fulfilled: f(x_lower) > f(x) and f(x) < f(x_upper), with x a first estimate of the location of the minimum.");
wasora_runtime_error();

because the two other errors which return a GSL_EINVAL status must fail with the their original GSL error message.

I would rather have to check the error message "endpoints do not enclose a minimum". Do you know how to access to that message?

@gtheler
Copy link
Contributor

gtheler commented Aug 14, 2019

no, but I would take a look at what the GSL_ERROR macro expands to and see where the string ends.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants