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

Inconsistent behavior on OSX vs Linux #59

Closed
dpo opened this issue Jul 15, 2015 · 18 comments
Closed

Inconsistent behavior on OSX vs Linux #59

dpo opened this issue Jul 15, 2015 · 18 comments

Comments

@dpo
Copy link
Contributor

dpo commented Jul 15, 2015

Here's an nl file that causes different behavior on OSX and Linux: https://gist.github.com/d190549c628ac44eda0e

A funny starting point is hard-coded in the nl file. Evaluating the objective and gradient at the initial point should either raise an IEEE overflow error, or set f(x0) = +Inf, and g(x0) = [Inf, -Inf]. On OSX, the latter happens, and the error code from objval and objgrd is set to zero (i.e., all seems well). On Linux however, the error code is nonzero, but the objective value and gradients contain junk.

Three users have confirmed this from the Julia interface, and from my simple miniampl driver.

Would you mind trying to reproduce this?

@vitaut
Copy link
Contributor

vitaut commented Jul 15, 2015

Thanks for the test case, I'll look into it.

@vitaut
Copy link
Contributor

vitaut commented Jul 15, 2015

I've tried to reproduce the issue on the following code on Linux:

#include "asl.h"

int main() {
  ASL *asl = ASL_alloc(ASL_read_fg);
  FILE *f = jac0dim("test.nl", 0);
  fg_read(f, 0);
  fint ne = 0;
  double x[] = {
    1028277.91612209
    -419876076.32321185
  };
  double objval = asl->p.Objval(asl, 0, x, &ne);
  printf("%g %d\n", objval, ne);
}

but it prints the objective value of 1.75438e+13 and error code 0. Is the x correct?

Also what is the objective function as I don't want to decrypt the nl file?

@dpo
Copy link
Contributor Author

dpo commented Jul 15, 2015

Yes the x looks ok. The answer you get is harmful because no error is raised. Here is the mod file: https://gist.github.com/af7cab05de61444b7e63

At the initial point, the argument of exp is about 8.4e+9, so there should clearly be an overflow in double precision.

EDIT: it would be great if you could try gcc and clang on Linux. We've tried both, and they both return wrong answers, which suggests something might be going on in the ASL.

@vitaut
Copy link
Contributor

vitaut commented Jul 15, 2015

D'oh. I missed the comma in the initializer list of x.

Now I get the nonzero error as expected and the objective value of 0 (with GCC and Linux) which looks OK to me as exp returns an error. I don't think you should rely on the value returned by Objval in case of error.

@vitaut
Copy link
Contributor

vitaut commented Jul 15, 2015

But I can reproduce that on OS X with clang the same code gives inf which is somewhat inconsistent.

@dpo
Copy link
Contributor Author

dpo commented Jul 15, 2015

You're right that we shouldn't rely on the value given by objval if an error is raised. But I feel the result should be the same on OSX and Linux. Michael Overton's book on IEEE computations suggests that Inf would be the correct result to return in this case (https://www.cs.nyu.edu/overton/book/corrections/over_and_under.pdf).

vitaut added a commit that referenced this issue Jul 16, 2015
@vitaut
Copy link
Contributor

vitaut commented Jul 16, 2015

I've implemented a tentative fix for this issue in cd05878, so the result should be the same now both on OS X and Linux (or Clang and GCC as it might be more of a compiler-related thing). However, ASL doesn't propagate the infinity or NaN value but uses a longjmp to exit function evaluation early in case of error.

@dpo
Copy link
Contributor Author

dpo commented Jul 17, 2015

Is there an option to propagate NaN and Inf values? Isn't that IEEE standard?

At any rate, we have to trap eval errors in the simplified C interface (we currently don't). I'll prepare a PR.

@vitaut
Copy link
Contributor

vitaut commented Jul 18, 2015

Is there an option to propagate NaN and Inf values?

No AFAICS.

Isn't that IEEE standard?

This is one of the options if you evaluate the whole expression (another being an exception). But the ASL doesn't evaluate the whole expression in case of error.

Is there any specific use case for which you need propagation of Infinity/NaN? We could change error handling to make it possible, but I'd rather avoid it unless there is a strong reason to do so.

@dpo
Copy link
Contributor Author

dpo commented Jul 23, 2015

I'm not sure if this is related, but I'm now getting a nonzero error code when evaluating the objective of problem HS9 at the initial point. Here is my nl file. The model is:

param pi := 3.14159;

var x {1..2};

minimize obj:
  sin(pi * x[1] / 12) * cos(pi * x[2] / 16);

subject to constr1: 4*x[1] - 3*x[2] = 0;

let x[1] := 0;
let x[2] := 0;

EDIT: To be clear, the error occurs in master. It does not occur in release 2.0.1.

@vepiteski
Copy link

Just a comment to motivate the necessity to propagate Inf: in a backtracking line search, Inf will certainly result in stepsize reduction and eventually success while an error code produces a failure.

@vitaut
Copy link
Contributor

vitaut commented Jul 24, 2015

@dpo Do you initialize error code to zero before calling Objval because it might be unchanged in case of success?

This test gives zero error code on the .nl file you provided:

  ASL *asl = ASL_alloc(ASL_read_fg);
  FILE *f = jac0dim("test.nl", 0);
  fg_read(f, 0);
  fint ne = 0;
  double x[] = { 0, 0 };
  double objval = asl->p.Objval(asl, 0, x, &ne);
  printf("%g %d\n", objval, ne); // prints 0 0

Hopefully no missing commas this time =).

@vepiteski Good point. I'll see if we can add an option to propagate infinity.

@dpo
Copy link
Contributor Author

dpo commented Jul 24, 2015

@vitaut I've tried setting ne to zero and not, and both give a nonzero error code. I'm using miniampl, which initializes ne to zero. This is on OSX. There might again be a difference of behavior with Linux. Could you please gist your entire driver so I can test it here?

@vitaut
Copy link
Contributor

vitaut commented Jul 24, 2015

Here's the complete test case. You are right, this can be a platform-specific issue. I tested on Linux but will try on OS X later.

@dpo
Copy link
Contributor Author

dpo commented Jul 24, 2015

Your driver also gives me an error code of 1. This is with clang on OSX 10.9 and your master branch.

@vitaut
Copy link
Contributor

vitaut commented Jul 24, 2015

I'll look into it. Thanks for testing.

@vitaut
Copy link
Contributor

vitaut commented Jul 24, 2015

This particular problem should be fixed in cb50826 although the same change should probably be done for constraint evaluation - I need to check this.

As for the Infinity & NaN propagation, looks like there is already an option for that, quoting changes:

Compiling rops.c and rops2.c with -DWANT_INFNAN will cause
them to return Infinities or NaNs in some cases where they would
otherwise report evaluation errors.

However, WANT_INFNAN is only handled for some operations at the moment.

@vitaut vitaut mentioned this issue Jul 24, 2015
@vitaut
Copy link
Contributor

vitaut commented Aug 20, 2015

Error handling should be consistent as of ASL 20150814 which has been merged into master.

@vitaut vitaut closed this as completed Aug 20, 2015
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

3 participants