Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

There is a method in nmatrix for matrix exponential? #622

Open
seoanezonjic opened this issue Nov 7, 2018 · 9 comments
Open

There is a method in nmatrix for matrix exponential? #622

seoanezonjic opened this issue Nov 7, 2018 · 9 comments

Comments

@seoanezonjic
Copy link

I need to use the matrix exponential operation as can be seen here:
https://www.mathworks.com/help/matlab/ref/expm.html
There is a method for this operation in nmatrix? If is not, how can I implement it using the nmatrix methods?
Thanks in advance

@translunar
Copy link
Member

I don't believe we've implemented one. I think the pseudocode for doing so is right there in the Matlab docs, so I'd be eager to get a pull request for it. (expm(X) = V*diag(exp(diag(D)))/V)

I also have code for a separate matrix exponential, for computing rotations, so if that's what you're looking for, I can point you that way. (It's in Python right now, and possibly has a bug.)

@seoanezonjic
Copy link
Author

Yeah the pseudocode is that but V and D are given for this matlab function:
[V,D] = eig(X)
The documentation is in https://es.mathworks.com/help/matlab/ref/eig.html . I cannot find which methods in nmatrix are equivalent to this eig(). I'm new handling nmatrix and the tutorials don't cover this kind of topics. If you can point me which methods are equivalent to matlab's I can code this function myself. Furthermore, I'm working in an investigation project developed only in ruby, so I need the nmatrix implementation.
Thanks in advance

@translunar
Copy link
Member

translunar commented Nov 8, 2018

The method you're looking for is from lapack and atlas. It's called geev.

You could look in:

The methods are documented elsewhere, but I find the specs are pretty good for seeing them actually used.

@seoanezonjic
Copy link
Author

I have installed nmatrix-lapacke to implement the matlab method but I have the following problem, when I use the method geev as:
eigenvalues, vl, vr = NMatrix::LAPACK.geev(nmatrix_object)
I have the following error:
geev requires either the nmatrix-atlas or nmatrix-lapack gem (NotImplementedError)
So, I added to my script this require:
require 'nmatrix-lapacke'
but it breaks with the following error:
require': cannot load such file -- nmatrix-lapacke (LoadError)
When I do a gem list, the gem is listed:

backports (3.11.4)
bigdecimal (default: 1.3.0)
bundler (1.16.1)
colorize (0.8.1)
io-console (default: 0.4.6)
json (default: 2.0.2)
nmatrix (0.2.4)
nmatrix-lapacke (0.2.4)
openssl (default: 2.0.3)
packable (1.3.10)
pp (0.1.1)
psych (default: 2.2.2)
rake (12.3.1)
rdoc (default: 5.0.0)

Both gems, nmatrix and nmatrix-lapacke are installed using gem install. How the libraries must be loaded? and how the methods must be invoked?

@translunar
Copy link
Member

I believe you want require "nmatrix/lapacke" and require "nmatrix/atlas".

@seoanezonjic
Copy link
Author

I have tested the require that you suggest to me and now I have de following error:

/mnt/home/soft/rvm/.rvm/rubies/ruby-2.4.1/lib64/ruby/site_ruby/2.4.0/rubygems/core_ext/kernel_require.rb:133:in `require': /mnt/home/users/pab_001_uma/pedro/.gem/ruby/2.4.1/gems/nmatrix-lapacke-0.2.4/lib/nmatrix_lapacke.so: undefined symbol: cblas_ctrsm - /mnt/home/users/pab_001_uma/pedro/.gem/ruby/2.4.1/gems/nmatrix-lapacke-0.2.4/lib/nmatrix_lapacke.so (LoadError)
	from /mnt/home/soft/rvm/.rvm/rubies/ruby-2.4.1/lib64/ruby/site_ruby/2.4.0/rubygems/core_ext/kernel_require.rb:133:in `rescue in require'
	from /mnt/home/soft/rvm/.rvm/rubies/ruby-2.4.1/lib64/ruby/site_ruby/2.4.0/rubygems/core_ext/kernel_require.rb:40:in `require'
	from /mnt/home/users/pab_001_uma/pedro/.gem/ruby/2.4.1/gems/nmatrix-lapacke-0.2.4/lib/nmatrix/lapacke.rb:35:in `<top (required)>'
	from /mnt/home/soft/rvm/.rvm/rubies/ruby-2.4.1/lib64/ruby/site_ruby/2.4.0/rubygems/core_ext/kernel_require.rb:133:in `require'
	from /mnt/home/soft/rvm/.rvm/rubies/ruby-2.4.1/lib64/ruby/site_ruby/2.4.0/rubygems/core_ext/kernel_require.rb:133:in `rescue in require'
	from /mnt/home/soft/rvm/.rvm/rubies/ruby-2.4.1/lib64/ruby/site_ruby/2.4.0/rubygems/core_ext/kernel_require.rb:40:in `require'
	from ../ruby_code/kernels.rb:3:in `<main>'

My sysadmim has perform a deep research and he has checked the libraries with ldd:

ldd ~/.gem/ruby/2.4.1/gems/nmatrix-lapacke-0.2.4/lib/nmatrix_lapacke.so
	linux-vdso.so.1 (0x00007ffe02b7e000)
	libruby.so.2.4 => /mnt/home/soft/rvm/.rvm/rubies/ruby-2.4.1/lib64/libruby.so.2.4 (0x00007faeeec05000)
	liblapack.so => /mnt/home/soft/scalapack/res/lapack/3.4.2/lib/liblapack.so (0x00007faeee266000)
	libpthread.so.0 => /lib64/libpthread.so.0 (0x00007faeee02d000)
	libgmp.so.10 => /usr/lib64/libgmp.so.10 (0x00007faeedda6000)
	libdl.so.2 => /lib64/libdl.so.2 (0x00007faeedba1000)
	libcrypt.so.1 => /lib64/libcrypt.so.1 (0x00007faeed966000)
	libstdc++.so.6 => /usr/lib64/libstdc++.so.6 (0x00007faeed5dd000)
	libm.so.6 => /lib64/libm.so.6 (0x00007faeed2df000)
	libc.so.6 => /lib64/libc.so.6 (0x00007faeecf3a000)
	libgcc_s.so.1 => /lib64/libgcc_s.so.1 (0x00007faeecd23000)
	/lib64/ld-linux-x86-64.so.2 (0x0000562137d69000)
	libblas.so => /mnt/home/soft/scalapack/res/lapack/3.4.2/lib/libblas.so (0x00007faeeca9f000)
	libimf.so => /mnt/home/soft/intel/programs/x86_64/composer_xe_2013.1.117/ipp/../compiler/lib/intel64/libimf.so (0x00007faeec5e3000)
	libifport.so.5 => /mnt/home/soft/intel/programs/x86_64/composer_xe_2013.1.117/ipp/../compiler/lib/intel64/libifport.so.5 (0x00007faeec3b4000)
	libifcore.so.5 => /mnt/home/soft/intel/programs/x86_64/composer_xe_2013.1.117/ipp/../compiler/lib/intel64/libifcore.so.5 (0x00007faeec07d000)
	libsvml.so => /mnt/home/soft/intel/programs/x86_64/composer_xe_2013.1.117/ipp/../compiler/lib/intel64/libsvml.so (0x00007faeeb7af000)
	libintlc.so.5 => /mnt/home/soft/intel/programs/x86_64/composer_xe_2013.1.117/ipp/../compiler/lib/intel64/libintlc.so.5 (0x00007faeeb560000)

What can be happening with this?
Thank you for your attention

@translunar
Copy link
Member

Have you followed the instructions on our wiki for installing ATLAS, lapacke, the gems, etc? It looks like you've got two versions installed and it's finding the wrong ones.

@seoanezonjic
Copy link
Author

Hi all
In the last months I have received other work to finish, so it was impossible to me with nmatrix. Now, I can work in this project without problem. I fix the installation problem with the following commands:

gem install nmatrix -- --with-ldflags"=-lopenblas" 
gem install nmatrix-lapacke -- --with-ldflags"=$LDFLAGS" 

With these lines, nmatrix installs succesfully. Also, I've implemented the exponetial matrix as follows (with the matlab documentation):

matrix = NMatrix.new([3, 3],[1, 1, 0, 0, 0, 2, 0, 0, -1], dtype: :float32)
eigenvalues, eigenvectors = NMatrix::LAPACK.geev(matrix, :right)
eigenvalues.map!{|val| Math.exp(val)}
numerator = eigenvectors.dot(NMatrix.diagonal(eigenvalues, dtype: :float32))
matrix_result = numerator.dot(eigenvectors.pinv) #Matrix division A/B => A.dot(B.pinv) 

With the toy example this code works, but when I use a bigger real matrix the Math.exp complains by receive complex numbers. How I can deal with this problem? There is another aproximation as power series or something?
Thank you in advance

@abourque72
Copy link

You could do a check for when val is complex. Say val = a+bi. Then exp(val) = exp(a) * (cos(b) + i * sin(b)). Lemme know if you find this useful.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants