-
Notifications
You must be signed in to change notification settings - Fork 15
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
Set a reasonable absolute tolerance to avoid spurious negatives for close-to-zero signals #66
Comments
Can you please add the two two-column CSV files where the behavior can be reproduced. |
@beutlich you can find many examples in PR modelica/ModelicaStandardLibrary#4420, where I first wanted to actually remove the offending signals from the CSV files. The idea is that this should not be necessary (i.e. the amended CSV-compare tool should pass the verification without removing those signals) with the change proposed in this ticket. |
This is a MWE of two CSV files that are expected to fail on CSV1:
CSV2:
Thanks! |
You saying "should be something like" implies to me that you're not totally sure about the specifics, yourself. To avoid coming up with some tolerance definition off-the-cuff (that maybe subtly differs from other similar functions, please let me suggest to use the one that Python's abs(v - v_ref) <= max(tol*max(abs(v), abs(v_ref)), nom) This is the same relation that Julia's NB: Numpy uses a slightly different formulation, which I personally don't like because it's not symmetric in its arguments, as abs(v - v_ref) <= nom + tol*abs(v_ref) |
I meant I didn't put too much effort in making a precise proposal, because of lack of time 😅 In fact, what I wanted to write was
(of course you need the absolute value on the LHS). This is equivalent to
it seems reasonable to me to take the max between abs(v) and abs(v_ref), as sugggested by @bilderbuchi . I'm not sure if that formula is sensible regarding nom, I guess it should be
as asking for
seems a bit too lax to me. Ditto for the Numpy implementation, I guess it should be
The idea is that the absolute value of the error should be less than the tolerance times the largest of three values: the variable itself, its reference value, and its nominal value, in order to avoid being too strict in cases where the variable is accidentally close to zero. @bilderbuchi are we on the same page? |
Of course this is based on the assumption that |
Yes, you are of course right. I made a sloppy mistake in "translating" the Python docs examples to your nomenclature above, in that I simply replaced |
@beutlich do you have a clear idea about how to proceed now? |
Not sure if I found the right place to consider nominal values, but this quick-and-dirty change could work: --- a/Modelica_ResultCompare/CurveCompare/TubeSize.cs
+++ b/Modelica_ResultCompare/CurveCompare/TubeSize.cs
@@ -126,7 +126,7 @@ namespace CurveCompare
{
double epsilon = 1e-12;
baseX = Math.Max(Math.Max(reference.X.Max() - reference.X.Min(), Math.Abs(reference.X.Min())), epsilon);
- ratio = Math.Max(Math.Max(reference.Y.Max() - reference.Y.Min(), Math.Abs(reference.Y.Min())), epsilon) / baseX;
+ ratio = Math.Max(Math.Max(Math.Max(reference.Y.Max() - reference.Y.Min(), Math.Abs(reference.Y.Min())), epsilon) / baseX, 0.001);
baseY = baseX * ratio;
return;
} |
@beutlich I'm trying to figure out the code you pointed out csv-compare/Modelica_ResultCompare/CurveCompare/TubeSize.cs Lines 99 to 132 in 18b309d
but I'm not familiar with it. The first question is: what is the difference between If Maybe we should also adapt |
I am neither sure what "former" and "standard" refers to. When debugging, I noticed that the "former" function is called. |
I'm confused about this part of the code, it seems to basically set the extent ( "Former" seems to refer to some formerly used method of computation:
|
The point where the tolerance should come into play is at
where the lower and upper extent of the tube around the reference are computed. (or the equivalent function in the Ellipse.cs file, I could not find out which one is ultimately used).
The confusing thing is that in that case the whole extent of the curve values would be used for creating the tube, which would be meaningless. Unfortunately, the code structure is full of indirections and similarly named variables, so it's very hard to find out more just using the Github code viewer. You'd have to analyze the program behaviour and results to find out if that is the case, and ideally add some tests with some constructed expected-pass and expected-fail curves to ensure the expected behaviour. AFAICT, this program does not have a test suite, yet. That's about as far as I can help, here -- I hope it does! |
I have no idea how this code actually works in detail, but to me the case is quite clear. The "former" code, which according to @beutlich is the one that is actually executed, computes
I'm not sure how exactly this Here, the range is (most reasonably) defined as So far so good, except that this results into too tight tubes when we have variables that are near zero because of balance equations, but are supposed to have a range which is much larger than the actual span of values in the result file. My argument (Ockham's razor rules!) is that we don't actually need to get into the details of how the tube algorithm works. We only need to make sure that Since we don't have nominal attribute in the CSV file, @HansOlsson pragmatic proposal, which I fully endorse, is to take a value of 0.001, which is small enough to avoid most of the false negatives we get now. The only drawback is that there could be some reference values with nominal values much smaller than this, in which case wrong values could be accepted. So be it, that's much better than removing the near-zero references altogether from the reference files, which would lead to accepting a lot more errors, potentially. I just created PR #67 based on these considerations. |
BTW, if |
We had many false regressions in the MSL on signals that are supposed to be zero but aren't, due to numerical errors, see modelica/ModelicaStandardLibrary#4421
One solution is to remove those signals outright, but then you can't really make sure that they are close to zero, so that's not a good solution in general, unless those close-to-zero signals are somehow redundant.
@HansOlsson in that ticket suggests a pragmatic but actually quite effective fix for this problem: set the tube width not only based on a relative tolerance, but also on some a-priori nominal value for signals, e.g. 1e-3. This means that the error criterion should be something like:
with nom = 1e-3 and tol = 0.002, the current setting for MSL testing.
@beutlich could you please take care of that at your earliest convenience?
Keeping @GallLeo in the loop.
The text was updated successfully, but these errors were encountered: