user2963343
user2963343

Reputation: 11

Is it possible to use methods from Ruby library in my own class?

I am trying to define Ruby classes for vectors and matrices. I intend to define two classes, MyVector and MyMatrix, with methods as hinted below. MyVector should represent a row vector, MyMatrix should represent a matrix, internally organized as an array of MyVector objects. Intended methods for MyVector:

  1. #initialize method, that takes an array of integers as argument.
  2. #length method, that returns the size of the vector.
  3. #* method, taking argument a, that:
    • if a is a vector, returns the inner product, validating that the size of a matches the receiver.
    • if a is a matrix, then it returns the product of the receiver and the matrix, validating the size compatibility.
  4. #to_s method, that returns a string representation of the receiver.

Methods for MyMatrix:

  1. #initialize method, that takes an array of arrays as argument, converts the inner arrays into row vecotrs (MyVector class), and arranges them into a matrix.
  2. #transpose method, that returns the receiver transposed.
  3. #* method, that takes MyMatrix object argument and returns the matrix product, validating size compatibility of the argument.
  4. #to_s method, that returns a string representation of the receiver.

This code I have written so far is below, but it doesn't work at all. I tried to define some method followed by the library class method (in matrix and vector class, they already define those method), but seem this way doesn't work because it always asks you to define something new. Could you please help me? Thanks!

class  MyVector 
  def initialize (a)
    if !(a.instance_of? Array)
      raise "must be an array"
    else
      @array = a
    end
  end

  def array
    @array
  end

  def to_s
    @array.to_s
  end

  def length
    @array.length
  end   

  def each2(a) # 
    raise Error, "Integer is not like Vector" if a.kind_of?(Integer)
    Vector.Raise Error if length != a.length
    return to_enum(:each2, a) unless block_given?
    length.times do |i|
      yield @array[i], a[i]
    end
    self
  end

  def * (a)
    Vector.Raise Error if length != a.length
    p = 0
    each2(a) {|a1, a2|p += a1 * a2}
    p
  end
end

class MyMatrix
  def initialize a
    @array=Array.new(a.length)
    i=0
    while(i<a.length)
      @array[i]=MyVector.new(a[i])
    end
  end

  def to_s
    @array.to_s
  end

  def transpose
    size=vectors[0].length
    arr= Array.new(size)
    i=0
    while i<size
      a=Array.new(vector.length)
      j=0
      while j<a.length
        a[j]=vectors[j].arr[i]
        j+=1
      end
      arr[i]=a
      i+=1
    end        
    arr[i]=a
    i+=1
  end   

  def *m
    if !(m instance_of? MyMatrix)
      raise Error
      a=Array.new(@array.length)
      i=0
      while (i<@array.length)
        a[i]=@array[i]*m  
        i=i+1      
      end
    end
  end
end

Upvotes: 0

Views: 120

Answers (1)

Boris Stitnicky
Boris Stitnicky

Reputation: 12578

A great question, and a great exercise for a newbie. As you might already know, Marc-André Lafortune has written the basic Matrix / Vector library, that is a part of Ruby standard library. While after the amount of effort that a programmer and mathematician, that Marc-André is, has put in the project, it is no longer possible to say that it sucks, it is also fair to say that stdlib matrix nowadays does not yet conform to that heavenly, dream-like quality that we expect of Ruby libraries.

My major criticism is that, just like you, Marc-André also makes a distinction between Vector and Matrix classes. This distinction shouldn't be: Vectors are simly matrices, whose second dimension is equal to 1. Separating Matrix and Vector leaves the user at loss as to which one to use, and that led me to banning Vector completely in the code that I write.

Neveretheless, it will be stdlib's matrix, that is going to be the answer to your post. If I understood it well, the question mark statement in your post seems to be:

"I tried to define some method ... but seem this way doesn't work because it always asks you to define something new. Could you please help me?"

In order to help you, I would answer: Start by using the matrix standard library. Simply type

require 'matrix'

In the next step, you will make a private copy of matrix library, that came with your Ruby installation, you will rename it to my_matrix, and require it no longer by require 'matrix', but by:

require './path/to/my/project/directory/my_matrix'

In the third step, you will start changing the behavior of the library that you just copied, and see when it breaks. Next, you will learn about unit testing, and learn to use stdlib's minitest. With that, you can define the desired behavior, and change the code until it meets the requirement.

In the 4th, 5th, ... nth step, you will be making a lot of big and small mistakes. And should your dedication to matrices and vectors in Ruby survive, you will be warmly welcome as a member of NMatrix team, the future grand version of representing matrices in Ruby.

Upvotes: 3

Related Questions