numo-linalg 0.1.4 → 0.1.5
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/numo/linalg/autoloader.rb +4 -2
- data/lib/numo/linalg/function.rb +66 -12
- data/lib/numo/linalg/version.rb +1 -1
- data/numo-linalg.gemspec +1 -1
- data/spec/linalg/function/expm_spec.rb +36 -0
- metadata +7 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: f1a7f32e07db68cc87340dc3245d9205026bd33c4ebc18b1cbef28f605f1a1d6
|
4
|
+
data.tar.gz: 1cb21ea35b2dacb1fb02d44317fb3684d9827635e4191aa7ecffd069edd214b1
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: c6125b1b665a2fbd87ecda093e1afea1ef85ca057e62921d95fa424dbe7e30d41d26c5c4caca57719d4c284ec33e179508b13d12c4de5e535c65c186eedc42eb
|
7
|
+
data.tar.gz: 1d7b3ac0fa98d70bb772674b4491d4d0285ef3303668a59299075c7a1595ff1796df745b73c30f34e295260d0b79df0aaf395b2742a912a292c1a618d92f116b
|
@@ -19,13 +19,15 @@ module Numo
|
|
19
19
|
# @return [String] name of loaded backend library (mkl/openblas/lapack)
|
20
20
|
def load_library
|
21
21
|
mkl_dirs = ['/opt/intel/lib', '/opt/intel/lib64', '/opt/intel/mkl/lib', '/opt/intel/mkl/lib64']
|
22
|
-
openblas_dirs = ['/opt/
|
22
|
+
openblas_dirs = ['/opt/OpenBLAS/lib', '/opt/OpenBLAS/lib64', '/opt/openblas/lib', '/opt/openblas/lib64',
|
23
|
+
'/usr/local/opt/openblas/lib']
|
23
24
|
atlas_dirs = ['/opt/atlas/lib', '/opt/atlas/lib64',
|
24
25
|
'/usr/lib/atlas', '/usr/lib64/atlas', '/usr/local/opt/atlas/lib']
|
25
26
|
lapacke_dirs = ['/opt/lapack/lib', '/opt/lapack/lib64', '/opt/local/lib/lapack',
|
26
27
|
'/usr/local/opt/lapack/lib']
|
27
28
|
opt_dirs = ['/opt/local/lib', '/opt/local/lib64', '/opt/lib', '/opt/lib64']
|
28
|
-
base_dirs = ['/usr/local/lib', '/usr/local/lib64', '/usr/lib', '/usr/lib64'
|
29
|
+
base_dirs = ['/usr/local/lib', '/usr/local/lib64', '/usr/lib', '/usr/lib64',
|
30
|
+
"/usr/lib/#{RbConfig::CONFIG['host_cpu']}-#{RbConfig::CONFIG['host_os']}"]
|
29
31
|
base_dirs.unshift(*ENV['LD_LIBRARY_PATH'].split(':')) unless ENV['LD_LIBRARY_PATH'].nil?
|
30
32
|
|
31
33
|
mkl_libs = find_mkl_libs([*base_dirs, *opt_dirs, *mkl_dirs])
|
data/lib/numo/linalg/function.rb
CHANGED
@@ -12,12 +12,19 @@ module Numo; module Linalg
|
|
12
12
|
# defined from data-types of arguments.
|
13
13
|
# @param [Symbol] func function name without BLAS char.
|
14
14
|
# @param args arguments passed to Blas function.
|
15
|
+
# @param kwargs keyword arguments passed to Blas function.
|
15
16
|
# @example
|
16
17
|
# c = Numo::Linalg::Blas.call(:gemm, a, b)
|
17
|
-
def self.call(func
|
18
|
+
def self.call(func, *args, **kwargs)
|
18
19
|
fn = (Linalg.blas_char(*args) + func.to_s).to_sym
|
19
20
|
fn = FIXNAME[fn] || fn
|
20
|
-
|
21
|
+
if kwargs.empty?
|
22
|
+
# This conditional branch is necessary to prevent ArgumentError
|
23
|
+
# that occurs in Ruby 2.6 or earlier.
|
24
|
+
send(fn, *args)
|
25
|
+
else
|
26
|
+
send(fn, *args, **kwargs)
|
27
|
+
end
|
21
28
|
end
|
22
29
|
|
23
30
|
end
|
@@ -34,12 +41,19 @@ module Numo; module Linalg
|
|
34
41
|
# defined from data-types of arguments.
|
35
42
|
# @param [Symbol,String] func function name without BLAS char.
|
36
43
|
# @param args arguments passed to Lapack function.
|
44
|
+
# @param kwargs keyword arguments passed to Lapack function.
|
37
45
|
# @example
|
38
46
|
# s = Numo::Linalg::Lapack.call(:gesv, a)
|
39
|
-
def self.call(func
|
47
|
+
def self.call(func, *args, **kwargs)
|
40
48
|
fn = (Linalg.blas_char(*args) + func.to_s).to_sym
|
41
49
|
fn = FIXNAME[fn] || fn
|
42
|
-
|
50
|
+
if kwargs.empty?
|
51
|
+
# This conditional branch is necessary to prevent ArgumentError
|
52
|
+
# that occurs in Ruby 2.6 or earlier.
|
53
|
+
send(fn, *args)
|
54
|
+
else
|
55
|
+
send(fn, *args, **kwargs)
|
56
|
+
end
|
43
57
|
end
|
44
58
|
|
45
59
|
end
|
@@ -1084,14 +1098,11 @@ module Numo; module Linalg
|
|
1084
1098
|
when n
|
1085
1099
|
resids = (x[n..-1,true].abs**2).sum(axis:0)
|
1086
1100
|
when NArray
|
1087
|
-
|
1088
|
-
|
1089
|
-
|
1090
|
-
|
1091
|
-
|
1092
|
-
# NArray does not suppurt this yet.
|
1093
|
-
resids[mask,true] = (x[mask,n..-1,true].abs**2).sum(axis:-2)
|
1094
|
-
end
|
1101
|
+
resids = (x[false,n..-1,true].abs**2).sum(axis:-2)
|
1102
|
+
## NArray does not suppurt this yet.
|
1103
|
+
# resids = x[false,0,true].new_zeros
|
1104
|
+
# mask = rank.eq(n)
|
1105
|
+
# resids[mask,true] = (x[mask,n..-1,true].abs**2).sum(axis:-2)
|
1095
1106
|
end
|
1096
1107
|
end
|
1097
1108
|
x = x[false,0...n,true]
|
@@ -1163,6 +1174,49 @@ module Numo; module Linalg
|
|
1163
1174
|
end
|
1164
1175
|
end
|
1165
1176
|
|
1177
|
+
# Compute the matrix exponential using Pade approximation method.
|
1178
|
+
#
|
1179
|
+
# @param a [Numo::NArray] square matrix (>= 2-dimensinal NArray)
|
1180
|
+
# @param ord [Integer] order of approximation
|
1181
|
+
# @return [Numo::NArray]
|
1182
|
+
# @example
|
1183
|
+
# a = Numo::Linalg.expm(Numo::DFloat.zeros([2,2]))
|
1184
|
+
# => Numo::DFloat#shape=[2,2]
|
1185
|
+
# [[1, 0],
|
1186
|
+
# [0, 1]]
|
1187
|
+
# b = Numo::Linalg.expm(Numo::DFloat[[1, 2], [-1, 3]] * Complex::I)
|
1188
|
+
# => Numo::DComplex#shape=[2,2]
|
1189
|
+
# [[0.426459+1.89218i, -2.13721-0.978113i],
|
1190
|
+
# [1.06861+0.489056i, -1.71076+0.914063i]]
|
1191
|
+
|
1192
|
+
def expm(a, ord=8)
|
1193
|
+
raise NArray::ShapeError, 'matrix a is not square matrix' if a.shape[0] != a.shape[1]
|
1194
|
+
|
1195
|
+
inf_norm = norm(a, 'inf')
|
1196
|
+
n_squarings = inf_norm.zero? ? 0 : [0, Math.log2(inf_norm).ceil.to_i].max
|
1197
|
+
a = a / (2**n_squarings)
|
1198
|
+
|
1199
|
+
sz_mat = a.shape[0]
|
1200
|
+
c = 1
|
1201
|
+
s = -1
|
1202
|
+
x = Numo::DFloat.eye(sz_mat)
|
1203
|
+
n = Numo::DFloat.eye(sz_mat)
|
1204
|
+
d = Numo::DFloat.eye(sz_mat)
|
1205
|
+
|
1206
|
+
(1..ord).each do |k|
|
1207
|
+
c *= (ord - k + 1).fdiv((2 * ord - k + 1) * k)
|
1208
|
+
x = a.dot(x)
|
1209
|
+
cx = c * x
|
1210
|
+
n += cx
|
1211
|
+
d += s * cx
|
1212
|
+
s *= -1
|
1213
|
+
end
|
1214
|
+
|
1215
|
+
res = solve(d, n)
|
1216
|
+
n_squarings.times { res = res.dot(res) }
|
1217
|
+
res
|
1218
|
+
end
|
1219
|
+
|
1166
1220
|
# @!visibility private
|
1167
1221
|
def _make_complex_eigvecs(w, vin) # :nodoc:
|
1168
1222
|
v = w.class.cast(vin)
|
data/lib/numo/linalg/version.rb
CHANGED
data/numo-linalg.gemspec
CHANGED
@@ -23,5 +23,5 @@ Gem::Specification.new do |spec|
|
|
23
23
|
spec.add_development_dependency "bundler"
|
24
24
|
spec.add_development_dependency "rake"
|
25
25
|
spec.add_development_dependency "rspec"
|
26
|
-
spec.add_runtime_dependency "numo-narray", ">= 0.9.
|
26
|
+
spec.add_runtime_dependency "numo-narray", ">= 0.9.1.4"
|
27
27
|
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'spec_helper'
|
4
|
+
|
5
|
+
RSpec.describe Numo::Linalg do
|
6
|
+
describe 'det' do
|
7
|
+
it 'raises ShapeError given a rectangular matrix as matrix A' do
|
8
|
+
expect { described_class.expm(Numo::DFloat.new(2, 3).rand) }.to raise_error(Numo::NArray::ShapeError)
|
9
|
+
end
|
10
|
+
|
11
|
+
it 'calculates matrix exponential of matrix without full eigenvectors' do
|
12
|
+
e = Math.exp(1)
|
13
|
+
err = (described_class.expm(Numo::DFloat[[1, 2], [0, 1]]) - Numo::DFloat[[e, 2 * e], [0, e]]).abs.sum(1).max
|
14
|
+
expect(err).to be < 1e-6
|
15
|
+
end
|
16
|
+
|
17
|
+
it 'calculates matrix exponential for matrix with large norm' do
|
18
|
+
tmp = Numo::DFloat[[-0.0995741, 0.0746806], [-0.199148, 0.149361]]
|
19
|
+
err = (described_class.expm(Numo::DFloat[[-147, 72], [-192, 93]]) - tmp).abs.sum(1).max
|
20
|
+
expect(err).to be < 1e-6
|
21
|
+
end
|
22
|
+
|
23
|
+
it 'calculates matrix exponential for diagonal matrix' do
|
24
|
+
err = (described_class.expm(Numo::DFloat[2, 3].diag) - Numo::NMath.exp(Numo::DFloat[2, 3]).diag).abs.sum(1).max
|
25
|
+
expect(err).to be < 1e-6
|
26
|
+
end
|
27
|
+
|
28
|
+
it 'returns identity matrix when given zero matrix' do
|
29
|
+
expect(described_class.expm(Numo::DFloat.zeros([2, 2]))).to eq(Numo::DFloat.eye(2))
|
30
|
+
end
|
31
|
+
|
32
|
+
it 'returns complex matrix when given complex matrix' do
|
33
|
+
expect(described_class.expm(rand_rect_complex_mat(2, 2))).to be_a(Numo::DComplex)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: numo-linalg
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.5
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Masahiro TANAKA
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2019-
|
12
|
+
date: 2019-12-30 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: bundler
|
@@ -59,14 +59,14 @@ dependencies:
|
|
59
59
|
requirements:
|
60
60
|
- - ">="
|
61
61
|
- !ruby/object:Gem::Version
|
62
|
-
version: 0.9.
|
62
|
+
version: 0.9.1.4
|
63
63
|
type: :runtime
|
64
64
|
prerelease: false
|
65
65
|
version_requirements: !ruby/object:Gem::Requirement
|
66
66
|
requirements:
|
67
67
|
- - ">="
|
68
68
|
- !ruby/object:Gem::Version
|
69
|
-
version: 0.9.
|
69
|
+
version: 0.9.1.4
|
70
70
|
description: Ruby/Numo Linear Algebra library with interface to BLAS/LAPACK.
|
71
71
|
email:
|
72
72
|
- masa16.tanaka@gmail.com
|
@@ -174,6 +174,7 @@ files:
|
|
174
174
|
- spec/linalg/function/eigh_spec.rb
|
175
175
|
- spec/linalg/function/eigvals_spec.rb
|
176
176
|
- spec/linalg/function/eigvalsh_spec.rb
|
177
|
+
- spec/linalg/function/expm_spec.rb
|
177
178
|
- spec/linalg/function/inv_spec.rb
|
178
179
|
- spec/linalg/function/ldl_spec.rb
|
179
180
|
- spec/linalg/function/lstsq_spec.rb
|
@@ -213,7 +214,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
213
214
|
- !ruby/object:Gem::Version
|
214
215
|
version: '0'
|
215
216
|
requirements: []
|
216
|
-
rubygems_version: 3.
|
217
|
+
rubygems_version: 3.1.2
|
217
218
|
signing_key:
|
218
219
|
specification_version: 4
|
219
220
|
summary: Ruby/Numo Linear Algebra library with BLAS/LAPACK
|
@@ -230,6 +231,7 @@ test_files:
|
|
230
231
|
- spec/linalg/function/eigh_spec.rb
|
231
232
|
- spec/linalg/function/eigvals_spec.rb
|
232
233
|
- spec/linalg/function/eigvalsh_spec.rb
|
234
|
+
- spec/linalg/function/expm_spec.rb
|
233
235
|
- spec/linalg/function/inv_spec.rb
|
234
236
|
- spec/linalg/function/ldl_spec.rb
|
235
237
|
- spec/linalg/function/lstsq_spec.rb
|