Re: Help with my vec matching function

2009-12-28 Thread ajuc
I would write this like that:

(def v #{[1 2 3]   [9 8 3]   [1 2]   [1]   [1 0 3 4]   [1 2 3 4 5]} )

(defn better-match [pattern match1 match2]
   ;;here choosing better matching vec from these 2 - sorry, I'm too
lazy :)
  )

(reduce #(better-match [1 2 3] %1 %2) [] v)

-- 
You received this message because you are subscribed to the Google
Groups Clojure group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en


Re: Help with my vec matching function

2009-12-28 Thread ajuc
I don't know if I understan correctly the requirements, but this is my
try.


(def v #{[1 2 3]   [9 8 3]   [1 2]   [1]   [1 0 3 4]   [1 2 3 4 5]} )

(defn matching [p v]
  (reduce + (map #(if (= %1 %2) 1 0) p v)))

(defn better-match [p v1 v2]
  (if
(or
  ( (matching p v1) (matching p v2))
  (and
 (= (matching p v1) (matching p v2)) ( (count v1) (count
v2
v1
v2))

(reduce #(better-match [1 2 4 4 5] %1 %2) [] v)

-- 
You received this message because you are subscribed to the Google
Groups Clojure group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en


Re: Help with my vec matching function

2009-12-28 Thread Robert Campbell
Thanks ajuc.

I updated the implementation to match your algorithm:

(defn closest-match
  Searches the haystack vecs for the closest match to the needle vec
  [#^IPersistentVector needle #^IPersistentVector haystack]
  (letfn [(matching [candidate]
(reduce + (map #(if (= %1 %2) 1 0) needle candidate)))
  (closest [v1 v2]
   (if (or ( (matching v1) (matching v2))
   (and (= (matching v1) (matching v2))
( (count v1) (count v2 v1 v2))]
(reduce #(closest %1 %2) [] haystack)))

It now factors in the second step, taking the shortest candidate.

(closest-match [1 2 3] #{[1 2 3] [9 8 3] [1 2] [1] [1 0 3 4] [1 2 3 4 5]})

now correctly returns [1 2 3] instead of [1 2 3 4 5]




On Mon, Dec 28, 2009 at 4:23 PM, ajuc aju...@gmail.com wrote:
 I don't know if I understan correctly the requirements, but this is my
 try.


 (def v #{[1 2 3]   [9 8 3]   [1 2]   [1]   [1 0 3 4]   [1 2 3 4 5]} )

 (defn matching [p v]
  (reduce + (map #(if (= %1 %2) 1 0) p v)))

 (defn better-match [p v1 v2]
  (if
    (or
      ( (matching p v1) (matching p v2))
      (and
         (= (matching p v1) (matching p v2)) ( (count v1) (count
 v2
    v1
    v2))

 (reduce #(better-match [1 2 4 4 5] %1 %2) [] v)

 --
 You received this message because you are subscribed to the Google
 Groups Clojure group.
 To post to this group, send email to clojure@googlegroups.com
 Note that posts from new members are moderated - please be patient with your 
 first post.
 To unsubscribe from this group, send email to
 clojure+unsubscr...@googlegroups.com
 For more options, visit this group at
 http://groups.google.com/group/clojure?hl=en

-- 
You received this message because you are subscribed to the Google
Groups Clojure group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en


Re: Help with my vec matching function

2009-12-28 Thread Robert Campbell
How might I add a third and final condition, where those candidates
with equal scores AND equal counts are all returned together?

A first try was this:

(defn closest-match
  Searches the haystack vecs for the closest match to the needle vec
  [#^IPersistentVector needle #^IPersistentVector haystack]
  (letfn [(matching [candidate]
(reduce + (map #(if (= %1 %2) 1 0) needle candidate)))
  (closest [v1 v2]
   (cond
 (and (= (matching v1) (matching v2))
  (= (count v1) (count v2))) [v1 v2]
 (or ( (matching v1) (matching v2))
 (and (= (matching v1) (matching v2))
  ( (count v1) (count v2 v1
 :else v2))]
(reduce #(closest %1 %2) [] haystack)))

(closest-match [1 2] #{[1 2 \a] [1 2 \b] [2 1]})
[[1 2 \b] [1 2 \a]]
(closest-match [1 2] #{[1 2] [1 2 \a] [1 2 \b] [2 1]})
[1 2]

It looks good at first, but I quickly noticed that I broke the whole
reduction by introducing a pair where we expend only a vec:

(closest-match [1 2] #{[1 2 \a] [1 2 \b] [2 1] [1 2 \c]})
[1 2 \a]

What we should be getting [[1 2 \a] [1 2 \b] [1 2 \c]] since each of
them is equally close to [1 2 3]




On Mon, Dec 28, 2009 at 5:20 PM, Robert Campbell rrc...@gmail.com wrote:
 Thanks ajuc.

 I updated the implementation to match your algorithm:

 (defn closest-match
  Searches the haystack vecs for the closest match to the needle vec
  [#^IPersistentVector needle #^IPersistentVector haystack]
  (letfn [(matching [candidate]
                    (reduce + (map #(if (= %1 %2) 1 0) needle candidate)))
          (closest [v1 v2]
                   (if (or ( (matching v1) (matching v2))
                           (and (= (matching v1) (matching v2))
                                ( (count v1) (count v2 v1 v2))]
    (reduce #(closest %1 %2) [] haystack)))

 It now factors in the second step, taking the shortest candidate.

 (closest-match [1 2 3] #{[1 2 3] [9 8 3] [1 2] [1] [1 0 3 4] [1 2 3 4 5]})

 now correctly returns [1 2 3] instead of [1 2 3 4 5]




 On Mon, Dec 28, 2009 at 4:23 PM, ajuc aju...@gmail.com wrote:
 I don't know if I understan correctly the requirements, but this is my
 try.


 (def v #{[1 2 3]   [9 8 3]   [1 2]   [1]   [1 0 3 4]   [1 2 3 4 5]} )

 (defn matching [p v]
  (reduce + (map #(if (= %1 %2) 1 0) p v)))

 (defn better-match [p v1 v2]
  (if
    (or
      ( (matching p v1) (matching p v2))
      (and
         (= (matching p v1) (matching p v2)) ( (count v1) (count
 v2
    v1
    v2))

 (reduce #(better-match [1 2 4 4 5] %1 %2) [] v)

 --
 You received this message because you are subscribed to the Google
 Groups Clojure group.
 To post to this group, send email to clojure@googlegroups.com
 Note that posts from new members are moderated - please be patient with your 
 first post.
 To unsubscribe from this group, send email to
 clojure+unsubscr...@googlegroups.com
 For more options, visit this group at
 http://groups.google.com/group/clojure?hl=en


-- 
You received this message because you are subscribed to the Google
Groups Clojure group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en


Re: Help with my vec matching function

2009-12-28 Thread ajuc


On 28 Gru, 20:57, Robert Campbell rrc...@gmail.com wrote:
 How might I add a third and final condition, where those candidates
 with equal scores AND equal counts are all returned together?

Reduce can work with functions like
f : x * y - x

So we can modify function closest to be like that (untested):

(closest [ v1s v2]
  (if  (empty v1s)
   v2
   (cond
 (and (= (matching (first v1s)) (matching v2))
  (= (count (first v1s)) (count v2))) (into
v1s v2))
 (or ( (matching (first v1s)) (matching v2))
 (and (= (matching (first v1s)) (matching v2))
  ( (count (first v1s)) (count v2
[v1]
 :else [v2])))

Also, we use matching on the same arguments a lot, so it would be good
to memoize that function.

-- 
You received this message because you are subscribed to the Google
Groups Clojure group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en


Re: Help with my vec matching function

2009-12-28 Thread Robert Campbell
That makes sense. I updated the function to:

(defn closest-match
  Returns the closest matches of needle in the haystack
  [#^IPersistentVector needle #^IPersistentVector haystack]
  (letfn [(matching [candidate]
(println  checking  candidate)
(reduce + (map #(if (= %1 %2) 1 0) needle candidate)))
  (closest [v1s v2]
   (cond (empty? v1s) [v2]
 (and (= (matching (first v1s)) (matching v2))
  (= (count (first v1s)) (count v2))) (conj v1s v2)
 (or ( (matching (first v1s)) (matching v2))
 (and (= (matching (first v1s)) (matching v2))
  ( (count (first v1s)) (count v2 v1s
 :else [v2]))]
(reduce #(closest %1 %2) [] haystack)))

This does work now:

(closest-match [1 2 3] #{[1 2 \a] [1 2 \b] [2 1] [1] [1 2 \c] [1 2 3 4 5]})
[[1 2 3 4 5]]

(closest-match [1 2] #{[1 2 \a] [1 2 \b] [2 1] [1] [1 2 \c] [1 2 3 4 5]})
[[1 2 \b] [1 2 \c] [1 2 \a]]

(closest-match [2 1 3] #{[1 2 \a] [1 2 \b] [2 1] [1] [1 2 \c] [1 2 3 4 5]})
[[2 1]]

One place I'm going to try to improve upon is how it reacts when there
are no matches. Right now, it will return the smallest candidate
because the third cond predicate will be true:
(and (= (matching (first v1s)) (matching v2))  ; (= 0 0)
   ( (count (first v1s)) (count v2 v1s  ; basically finds the
smallest candidate

(closest-match [\a \b] #{[1 2 \a] [1 2 \b] [2 1] [1] [1 2 \c] [1 2 3 4 5]})
[[1]]

(closest-match [\a \b] #{[1 2 \a] [1 2 \b] [2 1] [1] [1 2 \c] [1 2 3 4 5] []})
[[]]

I think when matches = 0, or there is literally no intersection
between the needle and the candidates, I will just return [].

Rob




On Mon, Dec 28, 2009 at 6:28 PM, ajuc aju...@gmail.com wrote:


 On 28 Gru, 20:57, Robert Campbell rrc...@gmail.com wrote:
 How might I add a third and final condition, where those candidates
 with equal scores AND equal counts are all returned together?

 Reduce can work with functions like
 f : x * y - x

 So we can modify function closest to be like that (untested):

 (closest [ v1s v2]
          (if  (empty v1s)
                   v2
                   (cond
                     (and (= (matching (first v1s)) (matching v2))
                          (= (count (first v1s)) (count v2))) (into
 v1s v2))
                     (or ( (matching (first v1s)) (matching v2))
                         (and (= (matching (first v1s)) (matching v2))
                              ( (count (first v1s)) (count v2
 [v1]
                     :else [v2])))

 Also, we use matching on the same arguments a lot, so it would be good
 to memoize that function.

 --
 You received this message because you are subscribed to the Google
 Groups Clojure group.
 To post to this group, send email to clojure@googlegroups.com
 Note that posts from new members are moderated - please be patient with your 
 first post.
 To unsubscribe from this group, send email to
 clojure+unsubscr...@googlegroups.com
 For more options, visit this group at
 http://groups.google.com/group/clojure?hl=en

-- 
You received this message because you are subscribed to the Google
Groups Clojure group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en


Re: Help with my vec matching function

2009-12-28 Thread Tom Hicks
A technique that works for me is to create sequences which are
augmented
with properties and then filter and transform those sequences in a
kind of pipeline.
Using that approach I came up with the following:

(defn eval-candidate [needle candidate]
  Returns a map representing derived information about the candidate
vector and its
   fit with the search target (needle) vector
  {:score (reduce + (map #(if (= %1 %2) 1 0) needle candidate))
   :len (count candidate)
   :vec candidate}
)

(defn closest-match [needle haystack]
  Tries to find the best fit for the given needle vector in the
   haystack of candidate vectors
  (let [augmented (map (partial eval-candidate needle) haystack)
max-score (apply max (map :score augmented))]
(if (= max-score 0)  ; no good matches
at all
  []
  (let [candidates (filter #(= max-score (:score %)) augmented)]
(if ( (count candidates) 1) ; a single match wins
  (let [min-length (apply min (map :len candidates))
winners (filter #(= min-length (:len %)) candidates)]
(map :vec winners) )
  (map :vec candidates)
  ) ) ) )
)

cheers,
-tom

-- 
You received this message because you are subscribed to the Google
Groups Clojure group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en