Model OrdF64 as a non-NaN float#972
Conversation
03a3a63 to
fba0e68
Compare
|
We actually have a much stronger invariant available than "not Rather than making a ton of functions like Similarly we should change The only places that a NaN can actually occur are where we do division -- I believe these are all in
|
|
I would propose splitting this into several commits:
|
|
@apoelstra Thank you so much for the detailed spec you provided, I believe this is ready for review, although you didn't mention, using |
|
Thanks! A few comments that should probably be addressed in followups:
|
|
Actually, given the quantity of these I think it'd be better to update the PR rather than doing a folowup. |
This was only made stable in Every other changes were addressed as stated. |
|
In cfb0336: You cannot have a You can call it In 3b0e7f9: You definitely should not be calling To handle 0 you will need to add some sort of To handle infinity I suspect you want to just back up, call the type |
Update the type name to better reflect its domain invariants. The underlying floats are guaranteed to be both positive and not-NaN, making `PositiveF64` a more accurate and descriptive name than `OrdF64`, which only highlighted the `Ord` trait implementation.
Add `Mul` and Add trait implementations for `PositiveF64` to enable arithmetic operations on `PositiveF64` values. Display impl is needed for `PositiveF64` to be used in `Policy`. Provide a `normalized` method on `PositiveF64` to normalize two values into a valid probability distribution. Implement the `k_over_n` method on `Threshold` to expose the threshold ratio (k / n) as a `PositiveF64`.
Introduce a `parse_probability` function to parse non-zero strings into PositiveF64 values. This implementation wraps around the `parse_num_nonzero` function to safely parse string inputs, enforcing the non-zero invariant.
Change `Or` weights from usize to PositiveF64 and all probability parameters from raw f64 to PositiveF64, making invalid states unrepresentable. Thread Threshold through the compiler instead of extracting k/n pairs. `parse_num_nonzero` visibility scope has been refactored to private the `parse_probability` method is now used in constructing the `Policy::Or` variant.
Replace ad-hoc `PositiveF64::new(0.0)` placeholders with Option-based patterns and a new conditional_add helper. - Add `PositiveF64::conditional_add` for adding an optional probability. - Change `compile_tern` branch weights from [PositiveF64; 2] to (PositiveF64, Option<PositiveF64>). - Switch tapleaf enumeration prob to Option<Reverse<PositiveF64>>. - Refactor `cost_1d` to use `conditional_add` instead of match branches.
`cargo +nightly rbmt lint` fails with useless use of `format!`, this patch fixes the culprit and uses `to_string` over the previously used `format!` macro.
|
I don't think we can entirely eliminate a constructor for this type, for the All cases where we were having Zero has been handled, the INFINITY extracted to a constant as |
|
I think I will need to take over this PR. I see no reason that |
|
Yeah, I see the complexity here. There are a bunch of changes that need to happen, possibly at once (though I'll try to untangle them into intellegible commits) if we want to eliminate all the constructors in compiler.rs. In particular, |
|
Further complicating things is that the compiler sometimes uses 0 probablities to mean "unsatisfiable". But I think this is confused logic that comes from the compiler attempting to be overly generic over different fragments. As always, as soon as I pull on one thing with this library it turns out there's a whole ediface of weird hacks that come tumbling down.. |
I think I handled the 0-probability case in 0243267 those were PositiveF64::new(0.0) placeholders, now replaced with Option + conditional_add. The real blocker going forward for me isindicating a fragment is free to satisfy. Unlike probabilities, the cost domain already encodes impossibility separately as INFINITY/f64::MAX, so zero isn't a sentinel there; it's a real number PositiveF64 can't represent.
To be fair, the initial commit was 8 years ago.. and a lot has evolved overtime. |
|
See #988 |
|
Costs cannot be But even probabilities are set to 0 sometimes in the current compiler, notably when handling the andor construction. |
|
Superceded by #988 |
PositiveRealnewtype for probability handlingSummary:
Replaces
f64andOrdF64withPositiveRealnewtype throughout the policy module, making invalid probability states unrepresentable at the type level.Changes:
OrdF64toPositiveReal.PositiveRealinto its own module.Add,Mul), display, andnormalizeforPositiveReal,ratioforThreshold.parse_probabilityhelper.PositiveRealin the policy module.closes #445