diff --git a/ChangeLog b/ChangeLog index 02fe6b0160..f34bf464d3 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +Thu Nov 20 02:44:27 2014 Marc-Andre Lafortune + + * lib/matrix.rb: Vector#independent? and associated class method + patch by gogo tanaka [#10451] + Thu Nov 20 02:32:34 2014 Marc-Andre Lafortune * lib/matrix.rb: Add Vector#angle_with diff --git a/NEWS b/NEWS index df5b64e961..b57eb3e91a 100644 --- a/NEWS +++ b/NEWS @@ -173,6 +173,7 @@ with all sufficient information, see the ChangeLog file. * Vector#cross_product generalized to arbitrary dimensions. * Vector#dot and #cross are aliases for #inner_product and #cross_product. * Vector#angle_with returns the angle with its argument + * New instance and class method independent? to test linear independence. * Pathname * Pathname#/ is aliased to Pathname#+. diff --git a/lib/matrix.rb b/lib/matrix.rb index 4d211ddd78..569680f600 100644 --- a/lib/matrix.rb +++ b/lib/matrix.rb @@ -1691,6 +1691,11 @@ end # * #each2(v) # * #collect2(v) # +# Properties of vectors: +# * #angle_with(v) +# * Vector.independent?(*vs) +# * #independent?(*vs) +# # Vector arithmetic: # * #*(x) "is matrix or number" # * #+(v) @@ -1699,7 +1704,6 @@ end # * #-@ # # Vector functions: -# * #angle_with(v) # * #inner_product(v), dot(v) # * #cross_product(v), cross(v) # * #collect @@ -1832,6 +1836,41 @@ class Vector end end + #-- + # PROPERTIES -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- + #++ + + # + # Returns +true+ iff all of vectors are linearly independent. + # + # Vector.independent?(Vector[1,0], Vector[0,1]) + # => true + # + # Vector.independent?(Vector[1,2], Vector[2,4]) + # => false + # + def Vector.independent?(*vs) + vs.each do |v| + raise TypeError, "expected Vector, got #{v.class}" unless v.is_a?(Vector) + Vector.Raise ErrDimensionMismatch unless v.size == vs.first.size + end + return false if vs.count > vs.first.size + Matrix[*vs].rank.eql?(vs.count) + end + + # + # Returns +true+ iff all of vectors are linearly independent. + # + # Vector[1,0].independent?(Vector[0,1]) + # => true + # + # Vector[1,2].independent?(Vector[2,4]) + # => false + # + def independent?(*vs) + self.class.independent?(self, *vs) + end + #-- # COMPARING -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- #++ diff --git a/test/matrix/test_vector.rb b/test/matrix/test_vector.rb index 9607755feb..9c33719455 100644 --- a/test/matrix/test_vector.rb +++ b/test/matrix/test_vector.rb @@ -89,6 +89,25 @@ class TestVector < Test::Unit::TestCase assert_equal(Vector[2.0,4.0,6.0], a) end + def test_independent? + assert(Vector.independent?(@v1, @w1)) + assert( + Vector.independent?( + Vector.basis(size: 3, index: 0), + Vector.basis(size: 3, index: 1), + Vector.basis(size: 3, index: 2), + ) + ) + + refute(Vector.independent?(@v1, Vector[2,4,6])) + refute(Vector.independent?(Vector[2,4], Vector[1,3], Vector[5,6])) + + assert_raise(Vector::TypeError) { Vector.independent?(@v1, 3) } + assert_raise(Vector::ErrDimensionMismatch) { Vector.independent?(@v1, Vector[2,4]) } + + assert(@v1.independent?(Vector[1,2,4], Vector[1,3,4])) + end + def test_mul assert_equal(Vector[2,4,6], @v1 * 2) assert_equal(Matrix[[1, 4, 9], [2, 8, 18], [3, 12, 27]], @v1 * Matrix[[1,4,9]])