-
Notifications
You must be signed in to change notification settings - Fork 108
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
Divide outside of floor #6130
Divide outside of floor #6130
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Beautiful!
Remember to capitalize your commit message.
You should know that the failing tests were setup as part of the refactoring process (moving from C++ to python), and to me it looks like the original had this bug to begin with. C++:
-static double trans_derrf(double x, const std::vector<double> arg) {
- int steps = arg[0];
- double min = arg[1];
- double max = arg[2];
- double skewness = arg[3];
- double width = arg[4];
- double y;
-
- y = floor(steps * 0.5 * (1 + erf((x + skewness) / (width * sqrt(2.0)))) /
- (steps - 1));
- return min + y * (max - min);
-}
Python:
+ def trans_derrf(x: float, arg: List[float]) -> float:
+ '''Observe that the argument of the shift should be \"+\"'''
+ _steps, _min, _max, _skew, _width = int(arg[0]), arg[1], arg[2], arg[3], arg[4]
+ y = math.floor(
+ _steps
+ * 0.5
+ * (1 + math.erf((x + _skew) / (_width * math.sqrt(2.0))))
+ / (_steps - 1)
+ )
+ return _min + y * (_max - _min) |
If
All hail hypothesis for finding this! |
Let's resolve #6166 as well |
Codecov Report
@@ Coverage Diff @@
## main #6130 +/- ##
==========================================
- Coverage 82.69% 82.65% -0.05%
==========================================
Files 351 347 -4
Lines 21536 21247 -289
Branches 839 834 -5
==========================================
- Hits 17810 17562 -248
+ Misses 3428 3387 -41
Partials 298 298
... and 23 files with indirect coverage changes 📣 We’re building smart automated test selection to slash your CI/CD build times. Learn more |
2efef67
to
bcff96d
Compare
This is ready for review |
Only coverage tests fail. |
b2c4c02
to
e7fa8ce
Compare
I may have found an example that fails:
Could you try running I also think that we should be able to get rid of the for-loop using for example def trans_derrf(x: float, arg: List[float]) -> float:
"""
Bin the result of `trans_errf` with `min=0` and `max=1` to closest of `nbins`
linearly spaced values on [0,1]. Finally map [0,1] to [min, max].
"""
_steps, _min, _max, _skew, _width = (
int(arg[0]),
arg[1],
arg[2],
arg[3],
arg[4],
)
q_values = np.linspace(start=0, stop=1, num=_steps)
q_checks = np.linspace(start=0, stop=1, num=_steps + 1)[1:]
y = TransferFunction.trans_errf(x, [0, 1, _skew, _width])
bin_index = np.digitize(y, q_checks, right=True)
y_binned = q_values[bin_index]
result = _min + y_binned * (_max - _min)
if result > _max or result < _min:
warnings.warn(
"trans_derff suffered from catastrophic loss of precision, clamping to min,max",
stacklevel=1,
)
return np.clip(result, _min, _max)
return result |
Reproducing the test I see
It seems that Edit: should probably also include a raise ValueError if the result is nan |
This is better, thanks. |
Tried running it a few times and
|
This is again due to precision. Resolving by restricting valid_derrf_parameters() even further |
84d5b33
to
6d18d7e
Compare
Issue
Resolves #6129
Approach
The part
is the cdf of a gaussian, so it yields something on the interval 0,1.
multiplying by steps and taking floor then yields steps different possibilities (intended)
the division should occur outside of floor to standardize to the 0, 1 interval again.