-
Notifications
You must be signed in to change notification settings - Fork 1.3k
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
improve monotonicity api #10117
improve monotonicity api #10117
Changes from 5 commits
fc0db97
349e12f
cbc08c1
b77eabb
d47b896
1266ed8
8379e7c
ea21acd
e5f72bb
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -346,13 +346,81 @@ impl Signature { | |
} | ||
} | ||
|
||
/// Monotonicity of the `ScalarFunctionExpr` with respect to its arguments. | ||
/// Each element of this vector corresponds to an argument and indicates whether | ||
/// the function's behavior is monotonic, or non-monotonic/unknown for that argument, namely: | ||
/// - `None` signifies unknown monotonicity or non-monotonicity. | ||
/// - `Some(true)` indicates that the function is monotonically increasing w.r.t. the argument in question. | ||
/// - Some(false) indicates that the function is monotonically decreasing w.r.t. the argument in question. | ||
pub type FuncMonotonicity = Vec<Option<bool>>; | ||
#[derive(Debug, Clone)] | ||
enum FuncMonotonicityPartial { | ||
/// not monotonic or unknown monotonicity | ||
None, | ||
/// Increasing with respect to all of its arguments | ||
Increasing, | ||
/// Decreasing with respect to all of its arguments | ||
Decreasing, | ||
/// Each element of this vector corresponds to an argument and indicates whether | ||
/// the function's behavior is monotonic, or non-monotonic/unknown for that argument, namely: | ||
/// - `None` signifies unknown monotonicity or non-monotonicity. | ||
/// - `Some(true)` indicates that the function is monotonically increasing w.r.t. the argument in question. | ||
/// - Some(false) indicates that the function is monotonically decreasing w.r.t. the argument in question. | ||
Mixed(Vec<Option<bool>>), | ||
} | ||
|
||
/// Monotonicity of a function with respect to its arguments. | ||
/// | ||
/// A function is [monotonic] if it preserves the relative order of its inputs. | ||
/// | ||
/// [monotonic]: https://en.wikipedia.org/wiki/Monotonic_function | ||
#[derive(Debug, Clone)] | ||
pub struct FuncMonotonicity(FuncMonotonicityPartial); | ||
|
||
impl FuncMonotonicity { | ||
pub fn new_none() -> Self { | ||
Self(FuncMonotonicityPartial::None) | ||
} | ||
pub fn new_increasing() -> Self { | ||
Self(FuncMonotonicityPartial::Increasing) | ||
} | ||
pub fn new_decreasing() -> Self { | ||
Self(FuncMonotonicityPartial::Decreasing) | ||
} | ||
pub fn new_mixed(inner: Vec<Option<bool>>) -> Self { | ||
Self(FuncMonotonicityPartial::Mixed(inner)) | ||
} | ||
|
||
/// returns true if this function is monotonically increasing with respect to argument number arg | ||
pub fn arg_increasing(&self, arg: usize) -> bool { | ||
match &self.0 { | ||
FuncMonotonicityPartial::None => false, | ||
FuncMonotonicityPartial::Increasing => true, | ||
FuncMonotonicityPartial::Decreasing => false, | ||
FuncMonotonicityPartial::Mixed(inner) => inner[arg].unwrap_or(false), | ||
} | ||
} | ||
|
||
/// returns true if this function is monotonically decreasing with respect to argument number arg | ||
pub fn arg_decreasing(&self, arg: usize) -> bool { | ||
match &self.0 { | ||
FuncMonotonicityPartial::None => false, | ||
FuncMonotonicityPartial::Increasing => false, | ||
FuncMonotonicityPartial::Decreasing => true, | ||
FuncMonotonicityPartial::Mixed(inner) => inner[arg].unwrap_or(false), | ||
} | ||
} | ||
} | ||
|
||
impl From<&FuncMonotonicity> for Vec<Option<bool>> { | ||
fn from(val: &FuncMonotonicity) -> Self { | ||
match &val.0 { | ||
FuncMonotonicityPartial::None => vec![None], | ||
FuncMonotonicityPartial::Increasing => vec![Some(true)], | ||
FuncMonotonicityPartial::Decreasing => vec![Some(false)], | ||
FuncMonotonicityPartial::Mixed(inner) => inner.to_vec(), | ||
} | ||
} | ||
} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I don't think this conversion is possible to do. Given only There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I agree with @ozankabak it is confusing to have a way to convert back to |
||
|
||
impl PartialEq for FuncMonotonicity { | ||
fn eq(&self, other: &Self) -> bool { | ||
Into::<Vec<Option<bool>>>::into(self) == Into::<Vec<Option<bool>>>::into(other) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Given my comment on There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Something like this perhaps: match (self, other) {
(Self::None, None) => true,
(Self::Increasing, Self::Increasing) => true,
(Self::Decreasing, Self::Decreasing) => true,
(Self::Partial(self_inner), Self::Partial(other_inner)) => self_inner == other_inner,
_ => false
} There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes. We also need to do configs like There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Maybe that type of comparsion belongs in something other than impl FuncMonotonicity {
fn matches(&self, &other) -> bool {
...
}
} So we can separate the equality check from the both sides match 🤔 |
||
} | ||
} | ||
|
||
#[cfg(test)] | ||
mod tests { | ||
|
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.
These public API's don't check the size of the inner vector. Giving a larger index would panic the code. We can wrap it with a result here.
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.
These APIs aren't being used anywhere. I think we can just remove them.
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.
Update:
I've removed the unused
arg_increasing
&arg_decreasing
public APIs.For reference, the only place we're currently using FuncMonotonicity is this:
https://github.com/tinfoil-knight/arrow-datafusion/blob/53d9e30a7561c97492e47e3ee1679885b6c510e6/datafusion/physical-expr/src/scalar_function.rs#L250-L263