You've got yourself a tricky problem, here.

The accepted way to compare how close two vectors or matrices are is to compute the norm of their difference - basically, the distance between them. The functions `matrix-absolute-error' and `matrix-relative-error' in `math/matrix' do that, and handle +inf.0, +nan.0 entries correctly. You can use `->col-matrix' to convert vectors to matrices; i.e.

    (matrix-relative-error (->col-matrix v1) (->col-matrix v2))

where `v2' is the assumed-correct vector. If this value is less than 1e-15, then (using the default error norm) the worst entry in `v1' has at least 15 correct digits (sort of). (If less than 1e-14, the worst entry has at least 14 correct digits, and so on.)

But you have a *set* of vectors. A straightforward way to test this is this way:

(require math/matrix)

(define (setof-vector=? vs1 vs2 [eps 1e-14])
  (let ([vs1  (map ->col-matrix (set->list vs1))]
        [vs2  (map ->col-matrix (set->list vs2))])
    (for/or ([vs1  (in-list (permutations vs1))])
      (for/and ([v1  (in-list vs1)]
                [v2  (in-list vs2)])
        (< (matrix-relative-error v1 v2) eps)))))

where `v2' is assumed to be the correct set of vectors. So we have

> (setof-vector=? (set #(4 5 6.00000000000001)
                       #(1 2 3.000000000000004))
                  (set #(1 2 3)
                       #(4 5 6)))
#t

> (setof-vector=? (set #(4 5 6.00000000000001)
                       #(1 2 3.00000000000004))
                  (set #(1 2 3)
                       #(4 5 6)))
#f


But we have to ask whether there is a *permutation* of `vs1' elements which, when matched up with those in `vs2', all have relative error less than `eps'. That's O(n!) in the number of elements.

There's probably a tricky way to do this efficiently, but I don't know what it is. You might find one in your problem domain; e.g. there may be a fast way to test whether a basis is approximately the same as another basis, particularly if they're each orthogonal.

If you could avoid approximate equality testing on sets, that would be even better. Without context, it's ambiguous. Even with context, it's hard to figure out. For example, what should the following test return?

> (setof-vector=? (set #(1.00000000000001 1.00000000000001)
                       #(0.99999999999999 0.99999999999999))
                  (set #(1 1)))

Neil ⊥

On 12/21/2013 04:34 PM, J G Cho wrote:
That looks very useful.


On Sat, Dec 21, 2013 at 6:23 PM, Greg Hendershott
<greghendersh...@gmail.com <mailto:greghendersh...@gmail.com>> wrote:

     > check-= wants single value but unfortunately my values are
    wrapped in set of vectors.

    Oh I didn't notice that.

    In that case you could define your own check -- that looks inside the
    sets and vectors to do the approximate equality test -- using the
    second variant of `define-binary-check` as described here:

    
http://docs.racket-lang.org/rackunit/api.html#%28form._%28%28lib._rackunit%2Fmain..rkt%29._define-binary-check%29%29




____________________
   Racket Users list:
   http://lists.racket-lang.org/users


____________________
 Racket Users list:
 http://lists.racket-lang.org/users

Reply via email to