solve function of gem NMatrix - ruby

When I tried to use the function "solve" in gem NMatrix, I find wrong result...
I am trying to solve the linear system a*x = b where
a = [[1, 0, 0],
[4, -5, 1],
[0, 0, 1]]
and
b = [0, 0, 729]
Which should give the answer
x = [0, 145.8, 729]
I call the solve function doing a.solve(b) (as explained at http://www.rubydoc.info/gems/nmatrix/0.2.1/NMatrix#solve-instance_method) but it returns
x = [0, 1.013500790889141e-30, 1.013500790889141e-30]
Therefore, I have two questions:
Am I doing something wrong?
If not, what would be the other solution (excluding GSL) to solve matrix systems with ruby?
Thank you !

To answer part 2 of your question, you can use Ruby's built-in Matrix class.
require 'matrix'
m = Matrix[[1, 0, 0], [4, -5, 1], [0, 0, 1]]
#=> Matrix[[1, 0, 0], [4, -5, 1], [0, 0, 1]]
b = Vector[0, 0, 729]
#=> Vector[0, 0, 729]
a = m.lup.solve(b).to_a
#=> [(0/1), (729/5), (729/1)]
If one prefers floats (rather than rational numbers),
a.map(&:to_f)
#=> [0.0, 145.8, 729.0]
See Matrix#lup and Matrix::LUPDecomposition#solve, which solve the linear system using LU decomposition.
If the system of linear equations has no solution (e.g., [[0,0], [0,0]]*x = b) or an infinite number of solutions (that is, m is singular), Ruby will raise an exception. For example,
Matrix[[0,0],[0,0]].lup.solve [1, 1]
#=> ExceptionForMatrix::ErrNotRegular: Not Regular Matrix
require matrix makes both the Matrix and Vector classes (and subclasses) available for use.

Related

Odd behavior with Ruby arrays?

I am using Ruby 2.3.1 and I cannot tell if I've encountered a bug or if this is intended behavior.
If you create an NxN matrix by making nested arrays, as such:
matrix = [[0]*5]*5
and then set the elements on the diagonals, as such:
(0..4).each {|i| matrix[i][i] = i}
this ends up affecting every column in every row:
[
[0, 1, 2, 3, 4],
[0, 1, 2, 3, 4],
[0, 1, 2, 3, 4],
[0, 1, 2, 3, 4],
[0, 1, 2, 3, 4]
]
Is this intended behavior?
P.S. I do not want to use Ruby's Matrix library, but would rather work with plain arrays.
Thanks in advance :)
In Ruby, arrays are, behind the scenes, objects of type array, which can contain primitive types and references to other objects. Now, this last bit is important - the array doesn't contain the object itself, but instead a pointer to it, which is interpreted as necessary when the programmer asks for it.
So the OP's original initialization code
matrix = [[0]*5]*5
Really creates a single array object containing 5 0s, and then copies the pointer to it 5 times. This also happens when you do
matrix = Array.new(5, Array.new(5, 0))
for precisely the same reason. So, as posted in the comments, the idiomatically correct Ruby way to create an array of 5 different array objects is
matrix = Array.new(5){Array.new(5, 0)}
Which yields a single array that contains pointers to 5 different array objects, preventing the issue encountered by the OP. Full documentation on the behaviour of Ruby arrays can be found at this finely-crafted link.
You don't need to change the diagonal to observe that behaviour; just change any element, say
matrix[1][1] = 1
Then
matrix
#=> [[0, 1, 0, 0, 0], [0, 1, 0, 0, 0], [0, 1, 0, 0, 0],
# [0, 1, 0, 0, 0], [0, 1, 0, 0, 0]]
Consider
matrix.map { |row| row.object_id }
#=> [70153694327100, 70153694327100, 70153694327100,
# 70153694327100, 70153694327100].
This shows that all elements ("rows") of matrix are the same object, ergo, if that object is changed, all elements of matrix are affected. matrix = [[0]*5]*5 is equivalent to
matrix = Array.new(5, Array.new(5,0))
(See Array::new, expecially "Common gotchas".) What you want (as #Sebastian notes) is
matrix = Array.new(5) { Array.new(5,0) }
#=> [[0, 0, 0, 0, 0], [0, 0, 0, 0, 0], [0, 0, 0, 0, 0],
# [0, 0, 0, 0, 0], [0, 0, 0, 0, 0]]
so that
matrix[1][1] = 1
only affects that one element:
matrix
#=> [[0, 0, 0, 0, 0], [0, 1, 0, 0, 0], [0, 0, 0, 0, 0],
# [0, 0, 0, 0, 0], [0, 0, 0, 0, 0]]
matrix = [[0]*5]*5
Let's break this down:
a = [0]*5
Create an array of 5 zeros; this is an array of integers.
matrix = [a] * 5
Create an array of 5 references to the same array a.
So of course when you modify one, the others will be modified; it's the same array.
I don't know Ruby, so please feel free to correct any incorrect terminology.

Introduction to algorithms 22.1-7 the contradiction in answer?

I am self-studying Introduction to algorithms, and am confused by the answer to 22.1-7.
Consider a directed graph with no self loop. I think it can be like picture3,
so the incidence matrix B should be
picture4
and the BT should be picture5
so The product of BBT should be picture6
i can understand the value in the diagonal means the the number of edge connect with the point
but in BBT[1][4] the value is 1 (0*1+(-1)*(-1)+(-1)*0)
i confused and don’t understand what wrong with it
To begin with, I think it's excellent that you actually tried to verify it with an example.
Unfortunately, you don't specify your edge numbers, so it's unclear what your incidence matrix refers to.
Suppose we use the following numbering:
Then the incidence matrix is
import numpy as np
b = np.array([[-1, -1, 0], [1, 0, 1], [0, 1, -1]])
>>> b
array([[-1, -1, 0],
[ 1, 0, 1],
[ 0, 1, -1]]
And the product is
>>> np.dot(b, b.T)
array([[ 2, -1, -1],
[-1, 2, -1],
[-1, -1, 2]])
which does not seem to be what you got, but actually makes a lot of sense.

Inserting values at empty indexes in arrays. How can I write this code shorter or more modular?

I have the following code I wrote which takes a 2d array with arrays of varying length and appends the value 0 to every index until all arrays are of the same length.
Can this code be written shorter or more efficient and modular?
a = [[1,7],[2,3],[5,1,2],[3],[1],[]]
l = a.map(&:length).max
a2 = a.each{|e| e.push(Array.new(l - e.length, 0) )}
a2.each{|e| e.flatten!}
#=> [[1, 7, 0], [2, 3, 0], [5, 1, 2], [3, 0, 0], [1, 0, 0], [0, 0, 0]]
UPDATE
Because I feel unable to award an accepted answer to the two answers given thus far based on the simplicity of the written code itself, I have decided to award it based on the efficiency of the running speed of the code.
100 test cases running code block 10000 times.
#My Code:
#average run time of test case -> 0.24267sec
#standard deviation -> 0.00735sec
#Stefan’s Code:
#average run time of test case -> 0.06389sec
#standard deviation -> 0.00756sec
#steenslag’s Code:
#average run time of test case -> 0.0577sec
#standard deviation -> 0.00413sec
tests were conducted under the same conditions using a custom written ruby timer class I made and are only relative to each other and my crappy 2010-macbookpro on which I ran them.
Another option using Array#fill:
l = a.map(&:length).max
a.each { |e| e.fill(0, e.length...l) }
a #=> [[1, 7, 0], [2, 3, 0], [5, 1, 2], [3, 0, 0], [1, 0, 0], [0, 0, 0]]
The flatten could be avoided by splatting the array:
l = a.max_by(&:size).size
a2 = a.each{|e| e.push(*Array.new(l - e.length, 0) )}
One more way, four days late:
len = a.map(&:size).max
a.map { |e| Array.new(len) { |i| e[i].to_i } }
#=> [[1,7,0],[2,3,0],[5,1,2],[3,0,0],[1,0,0],[0,0,0]]

How do I add columns and rows to a Matrix in Ruby?

If I have an existing Matrix in Ruby, how can I add a column or row of new data?
What I want to do is something like this:
require 'Matrix'
my_matrix = Matrix.diagonal(1,2,3)
my_matrix.append_row!([3,2,1])
my_matrix.append_column!([3,2,1])
Is there a way to do this?
Since doing this isn't (so far as I know) a valid matrix operation in the mathematical sense, there's nothing to do this in place. You can create a new Matrix though:
m = Matrix.diagonal(1, 2, 3)
#=> Matrix[[1, 0, 0], [0, 2, 0], [0, 0, 3]]
Matrix.columns(m.to_a << [4, 5, 6])
#=> Matrix[[1, 0, 0, 4], [0, 2, 0, 5], [0, 0, 3, 6]]
Matrix.rows(m.to_a << [4, 5, 6])
#=> Matrix[[1, 0, 0], [0, 2, 0], [0, 0, 3], [4, 5, 6]]
This uses columns or rows to create a new matrix by adding a new array
to the array representation of the original matrix.
I suspect the methods you are looking for are [hstack][1] and vstack.

I have a Strange output i do not expect. its similar but.. well odd

So ive taken up Prolog and im trying to learn the ropes of it. Right now im working on a assignment set by the book and ive come quite far. My output nearly matches that which is required but somehow its makes the last few lests that come out come out in a head|tail format in which the tail is a row of dots?
The code ive written looks like this:
%prefix methode. E1 + L = L1
% It takes L, adds E1 in front of it and makes it L1.
prefix(_,[],[]).
prefix(El,[LHead|LTail],[Q|L1]) :- Q = [El|LHead], prefix(El,LTail,L1).
gray(0,[[]]).
gray([],[]).
% this should generate a list of all the gray
% code possibilities with the defined length
gray(N,Lijst) :- N > 0, X is N - 1, gray(X,Prevlist),
reverse(Prevlist, RevPrevlist), prefix(0,Prevlist,Deel1),
prefix(1,RevPrevlist,Deel2), append(Deel1,Deel2,Lijst).
Now the thing it should do is if I give him for example -?gray(3,List).
It should tell me:
List = [[0,0,0],[0,0,1],[0,1,1],[0,1,0],[1,1,0],[1,1,1],[1,0,1],[1,0,0]].
However what it tells me instead is:
List = [[0, 0, 0], [0, 0, 1], [0, 1, 1], [0, 1, 0], [1, 1, 0], [1, 1, 1], [1, 0|...], [1|...]].
As you can see with the output I get my last two lasts have a head|tail construction with a tail consisting of dots. However I do not know what this means or what I did wrong in my code.
Can anybody elaborate why I am getting the dots, and maybe steer me in the right direction to help me solve the problem?
P.S. my apologies if I might've been unclear on certain parts. If I've been so, please say so and I'll try to edit/elaborate.
I just ran this through on swi-prolog:
2 ?- grey(3, List).
Correct to: "gray(3,List)"? yes
List = [[0, 0, 0], [0, 0, 1], [0, 1, 1], [0, 1, 0], [1, 1, 0], [1, 1, 1], [1, 0|...], [1|...]] [write]
List = [[0, 0, 0], [0, 0, 1], [0, 1, 1], [0, 1, 0], [1, 1, 0], [1, 1, 1], [1, 0, 1], [1, 0, 0]]
Notice where it said [write].. I press the 'w' button at that point which forces swi-prolog to dump out the whole list, not just appreviate it with the ...
Not sure if that helps, or if the answer is correct.
If not, suggest explaining the problem/assignment itself in a bit more detail. You've explained your solution in some detail, but it's not clear what the problem is ? To me, anyway.
Edit I see you have edited to clarify.. yep, just looks like prolog was abbreviating the results visually, but was actually holding the correct result. A 'display only' issue.

Resources