Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I pre-determine mutually exclusive comparisons?

Tags:

algorithm

r

The human eye can see that no value x satisfies the condition

x<1 & x>2

but how can I make R see that. I want to use this in a function which gets passed comparisons (say as strings) and not necessarily data. Let's say I want to write a function that checks whether a combination of comparisons can ever be fulfilled anyway, like this

areTherePossibleValues <- function(someString){
    someCode
}

areTherePossibleValues("x<1 & x>2")
[1] FALSE

I mean one could do that by interpreting the substrings that are comparison signs and so on, but I feel like there's got to be a better way. The R comparison functions ('<','>','=' and so on) themselves actually might be the answer to this, right?

like image 410
Georgery Avatar asked Jan 26 '17 09:01

Georgery


2 Answers

Another option is to use the library validatetools (disclaimer, I'm its author).

library(validatetools)

rules <- validator( r1 = x < 1, r2 = x > 2)
is_infeasible(rules)
# [1] TRUE

make_feasible(rules)
# Dropping rule(s): "r1"
# Object of class 'validator' with 1 elements:
#  r2: x > 2
# Rules are evaluated using locally defined options

# create a set of rules that all must hold:
rules <- validator( x > 1, x < 2, x < 2.5)
is_infeasible(rules)
# [1] FALSE

remove_redundancy(rules)
# Object of class 'validator' with 2 elements:
#  V1: x > 1
#  V2: x < 2

rules <- validator( x >= 1, x < 1)
is_infeasible(rules)
# [1] TRUE
like image 196
edwindj Avatar answered Oct 21 '22 13:10

edwindj


To compare among ranges, min of the range max(s) should always be greater than the max of the range min(s), showed as below:

library(dplyr)

library(stringr)

areTherePossibleValues <- function(s) {

  str_split(s, pattern = " *& *", simplify = TRUE)[1, ] %>% 

    {lapply(c("max" = "<", "min" = ">"), function(x) str_subset(., pattern = x) %>% str_extract(., pattern = "[0-9]+"))} %>% 

    {as.numeric(min(.$max)) > as.numeric(max(.$min))}

}

Update: add inclusion comparison

The only difference is that min of the range max(s) can be equal to the max of the range min(s).

library(dplyr)

library(stringr)

areTherePossibleValues <- function(s) {

  str_split(s, pattern = " *& *", simplify = TRUE)[1, ] %>% 

    {lapply(c("max" = "<", "min" = ">"), function(x) str_subset(., pattern = x) %>% str_remove(., pattern = paste0("^.*", x)))} %>% 

    {ifelse(sum(grepl(pattern = "=", unlist(.))), 

            as.numeric(min(str_remove(.$max, "="))) >= as.numeric(max(str_remove(.$min, "="))), 

            as.numeric(min(.$max)) > as.numeric(max(.$min)))}

}

areTherePossibleValues("x<1 & x>2")

areTherePossibleValues("x>1 & x<2")

areTherePossibleValues("x>=1 & x<1")
like image 25
Kevin Ho Avatar answered Oct 21 '22 13:10

Kevin Ho