Last active
December 10, 2015 06:07
-
-
Save Centril/18606483f883c17d9694 to your computer and use it in GitHub Desktop.
Fuzzy predicate logic searching with relevance, HOF style.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
interface SearchResult<T> { | |
T getResult(); | |
double getRelevance(); | |
// Just for being able to "clone" with other relevance... | |
SearchResult<? extends T> withRelevance( double relevance ); | |
} | |
interface SearchCriteria<T> { | |
SearchResult<? extends T> apply( SearchResult<? extends T> result ); | |
} | |
interface SearchQuery<T> { | |
List<? extends SearchCriteria<? extends T>> getCriterias(); | |
} | |
class AndCriteria<T> implements SearchCriteria<T> { | |
SearchCriteria<? extends T> left; | |
SearchCriteria<? extends T> right; | |
AndCriteria( SearchCriteria<? extends T> left, SearchCriteria<? extends T> right ) { | |
this.left = left; | |
this.right = right; | |
} | |
SearchResult<? extends T> apply( SearchResult<? extends T> result ) { | |
double r = result.getRelevance(); | |
return result.withRelevance( left.apply( result ).getRelevance() > r && | |
right.apply( result).getRelevance() > r | |
? r * 4 | |
: 0 ); | |
} | |
} | |
class OrCriteria<T> implements SearchCriteria<T> { | |
SearchCriteria<? extends T> left; | |
SearchCriteria<? extends T> right; | |
OrCriteria( SearchCriteria<? extends T> left, SearchCriteria<? extends T> right ) { | |
this.left = left; | |
this.right = right; | |
} | |
SearchResult<? extends T> apply( SearchResult<? extends T> result ) { | |
double r = result.getRelevance(); | |
return result.withRelevance( left.apply( result ).getRelevance() > r || | |
right.apply( result).getRelevance() > r | |
? r * 2 | |
: r / 2 ); | |
} | |
} | |
class NotCriteria<T> implements SearchCriteria<T> { | |
SearchCriteria<? extends T> criteria; | |
NotCriteria( SearchCriteria<? extends T> criteria ) { | |
this.criteria = criteria; | |
} | |
SearchResult<? extends T> apply( SearchResult<? extends T> result ) { | |
return result.withRelevance( result.getRelevance() * r - | |
criteria.apply( result ).getRelevance() ); | |
} | |
} | |
import java.util.function.Function; | |
import java.util.function.BiPredicate; | |
class MatchesCriteria<I, T> implements SearchCriteria<T> { | |
I input; | |
BiPredicate<? extends I, ? extends I> predicate; | |
Function<? extends T, ? extends I> transform; | |
MatchesCriteria( I input, | |
Function<? extends T, ? extends I> transform, | |
BiPredicate<? extends I, ? extends I> predicate ) { | |
this.input = input; | |
this.predicate = predicate; | |
this.transform = transform; | |
} | |
SearchResult<? extends T> apply( SearchResult<? extends T> sr ) { | |
double r = sr.getRelevance(); | |
return sr.withRelevance( predicate.test( input, | |
transform.apply( sr.getResult() ) ) | |
? r * 2 | |
: r / 2 ); | |
} | |
} | |
import java.util.stream.Stream; | |
class Searcher<T> { | |
List<SearchResult<? extends T>> search( List<SearchResult<? extends T>> results, | |
SearchQuery<? extends T> query ) { | |
Stream<SearchResult<? extends T>> stream = results.stream(); | |
for ( SearchCriteria<? extends T> criteria : query.getCriterias() ) { | |
stream = stream.map( criteria ) | |
} | |
return stream.filter( { sr -> sr.getRelevance() >= 1 } ) | |
.collect( Collectors.toList() ); | |
} | |
} | |
class ConcreteSR<T> implements SearchResult<T> { | |
T result; | |
double relevance; | |
ConcreteSR( T r, double rel ) { | |
result = r; | |
relevance = rel; | |
} | |
// Just for being able to "clone" with other relevance... | |
SearchResult<? extends T> withRelevance( double relevance ) { | |
return new ConcreteSR( result, relevance ); | |
} | |
} | |
def static main( args ) { | |
def r = new MatchesCriteria( 4, { ++it }, { input, v -> input == 2 * v } ) | |
.apply( new ConcreteSR<Integer>( 1, 1 ) ); | |
System.out.println( r.getRelevance() ); | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
-- Types: | |
type Frac = Double | |
data SearchResult a = SR { result :: a, relevance :: Frac } | |
type SearchCriteria a = SearchResult a -> SearchResult a | |
type SearchQuery a = [SearchCriteria a] | |
-- APIs: | |
andCriteria :: SearchCriteria a -> SearchCriteria a -> SearchCriteria a | |
andCriteria l r = mapResult (\sr rel -> if relevance (l sr) > rel && | |
relevance (r sr) > rel | |
then rel * 4 | |
else 0) | |
orCriteria :: SearchCriteria a -> SearchCriteria a -> SearchCriteria a | |
orCriteria l r = mapResult (\sr rel -> doubleOrHalf rel $ | |
relevance (l sr) > rel || | |
relevance (r sr) > rel) | |
andCriteria2 :: SearchCriteria a -> SearchCriteria a -> SearchCriteria a | |
andCriteria2 l r = mapResult (\sr rel -> min (relevance $ l sr) | |
(relevance $ r sr)) | |
orCriteria2 :: SearchCriteria a -> SearchCriteria a -> SearchCriteria a | |
orCriteria2 l r = mapResult (\sr rel -> max (relevance $ l sr) | |
(relevance $ r sr)) | |
notCriteria :: SearchCriteria a -> SearchCriteria a | |
notCriteria c = mapResult (\sr rel -> 2 * rel - relevance (c sr)) | |
matchesCriteria :: b -> (a -> b) -> (b -> b -> Bool) -> SearchCriteria a | |
matchesCriteria obj f p = mapResult (\sr rel -> | |
(doubleOrHalf rel . p obj . f . result) sr) | |
search :: [SearchResult a] -> SearchQuery a -> [SearchResult a] | |
search results criterias = filter ((>= 1) . relevance) $ | |
(foldl $ flip map) results criterias | |
search2 :: [a] -> SearchQuery a -> [SearchResult a] | |
search2 = search . map (flip SR 1) | |
-- Helpers: | |
doubleOrHalf :: Frac -> Bool -> Frac | |
doubleOrHalf r s = if s then r * 2 else r / 2 | |
mapResult :: (SearchResult a -> Frac -> Frac) -> SearchResult a -> SearchResult a | |
mapResult f sr@(SR a r) = SR a (f sr r) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment