cmdstan 0.1.8 → 0.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +18 -0
- data/README.md +24 -5
- data/lib/cmdstan/install.rb +100 -0
- data/lib/cmdstan/mcmc.rb +1 -1
- data/lib/cmdstan/model.rb +6 -2
- data/lib/cmdstan/version.rb +1 -1
- data/lib/cmdstan.rb +6 -0
- metadata +6 -8
- data/ext/cmdstan/Makefile +0 -5
- data/ext/cmdstan/extconf.rb +0 -68
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: d2453efa50e8efc908919f7366531f5bde5d4c619c913360c2a13fe4b5cd131d
|
4
|
+
data.tar.gz: c0c185c461629fef5231c0378e655dc7f85dc89add5f20c990483a9951a1cb49
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: d7741eeb4d5a61ba2f6bbd13039f2eac8ee44abe456d25b2785d02f6e974b98179d8e49f9e5ec255c86465b8a940121c6f7f152ea7278003f29542eb18847767
|
7
|
+
data.tar.gz: '052084d4bc7228885851cc2d8d9355272d97e98c40a8849938e3912411075c4410f16dcca20de3692460cdd5ae8d6d62ce96c1e18af13b358e96b175c0663f71'
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,21 @@
|
|
1
|
+
## 0.2.1 (2022-07-06)
|
2
|
+
|
3
|
+
- Updated CmdStan to 2.30.0
|
4
|
+
- Fixed error when `chains` not specified
|
5
|
+
|
6
|
+
## 0.2.0 (2022-04-23)
|
7
|
+
|
8
|
+
- CmdStan now installs when the first model is compiled rather than on gem installation
|
9
|
+
- Added `cmdstan_installed?` and `install_cmdstan` methods
|
10
|
+
- Updated CmdStan to 2.29.2
|
11
|
+
- Fixed issue with `summary` method
|
12
|
+
- Dropped support for Ruby < 2.7
|
13
|
+
|
14
|
+
## 0.1.9 (2022-02-07)
|
15
|
+
|
16
|
+
- Added support for Linux ARM
|
17
|
+
- Updated CmdStan to 2.28.2
|
18
|
+
|
1
19
|
## 0.1.8 (2022-01-16)
|
2
20
|
|
3
21
|
- Updated CmdStan to 2.28.1
|
data/README.md
CHANGED
@@ -9,11 +9,9 @@ Bayesian inference for Ruby, powered by [CmdStan](https://github.com/stan-dev/cm
|
|
9
9
|
Add this line to your application’s Gemfile:
|
10
10
|
|
11
11
|
```ruby
|
12
|
-
gem
|
12
|
+
gem "cmdstan"
|
13
13
|
```
|
14
14
|
|
15
|
-
Installation can take a few minutes as CmdStan downloads and builds.
|
16
|
-
|
17
15
|
## Getting Started
|
18
16
|
|
19
17
|
Create a Stan file, like `bernoulli.stan`
|
@@ -32,7 +30,7 @@ model {
|
|
32
30
|
}
|
33
31
|
```
|
34
32
|
|
35
|
-
Compile the model
|
33
|
+
Compile the model (this can take a few minutes the first time as CmdStan downloads and builds)
|
36
34
|
|
37
35
|
```ruby
|
38
36
|
model = CmdStan::Model.new(stan_file: "bernoulli.stan")
|
@@ -51,6 +49,14 @@ Summarize the results
|
|
51
49
|
fit.summary
|
52
50
|
```
|
53
51
|
|
52
|
+
Load a compiled model
|
53
|
+
|
54
|
+
```ruby
|
55
|
+
model = CmdStan::Model.new(exe_file: "bernoulli")
|
56
|
+
```
|
57
|
+
|
58
|
+
Check out [Strata](https://github.com/ankane/strata) for shipping models
|
59
|
+
|
54
60
|
## Maximum Likelihood Estimation
|
55
61
|
|
56
62
|
```ruby
|
@@ -58,6 +64,20 @@ mle = model.optimize(data: data)
|
|
58
64
|
mle.optimized_params
|
59
65
|
```
|
60
66
|
|
67
|
+
## Reference
|
68
|
+
|
69
|
+
Check if CmdStan is installed
|
70
|
+
|
71
|
+
```ruby
|
72
|
+
CmdStan.cmdstan_installed?
|
73
|
+
```
|
74
|
+
|
75
|
+
Install CmdStan manually
|
76
|
+
|
77
|
+
```ruby
|
78
|
+
CmdStan.install_cmdstan
|
79
|
+
```
|
80
|
+
|
61
81
|
## Credits
|
62
82
|
|
63
83
|
This library is modeled after the [CmdStanPy API](https://github.com/stan-dev/cmdstanpy).
|
@@ -81,6 +101,5 @@ To get started with development:
|
|
81
101
|
git clone https://github.com/ankane/cmdstan-ruby.git
|
82
102
|
cd cmdstan-ruby
|
83
103
|
bundle install
|
84
|
-
bundle exec ruby ext/cmdstan/extconf.rb
|
85
104
|
bundle exec rake test
|
86
105
|
```
|
@@ -0,0 +1,100 @@
|
|
1
|
+
module CmdStan
|
2
|
+
module Install
|
3
|
+
def cmdstan_version
|
4
|
+
"2.30.0"
|
5
|
+
end
|
6
|
+
|
7
|
+
def cmdstan_installed?
|
8
|
+
Dir.exist?(CmdStan.path)
|
9
|
+
end
|
10
|
+
|
11
|
+
def install_cmdstan
|
12
|
+
version = cmdstan_version
|
13
|
+
dir = CmdStan.path
|
14
|
+
|
15
|
+
# no stanc3 binary for Mac ARM
|
16
|
+
if RbConfig::CONFIG["host_os"] !~ /darwin/i && RbConfig::CONFIG["host_cpu"] =~ /arm|aarch64/i
|
17
|
+
checksum = "8ab1eaa83af100336e31fed1bcb854f30e7f775feb1274552fc706ed177969ef"
|
18
|
+
url = "https://github.com/stan-dev/cmdstan/releases/download/v#{version}/cmdstan-#{version}-linux-arm64.tar.gz"
|
19
|
+
else
|
20
|
+
checksum = "009c2ea0043aa4a91c03ac78932e64f3cff4faa3e73413a2e0269d5be2d8de6c"
|
21
|
+
url = "https://github.com/stan-dev/cmdstan/releases/download/v#{version}/cmdstan-#{version}.tar.gz"
|
22
|
+
end
|
23
|
+
|
24
|
+
puts "Installing CmdStan version: #{version}"
|
25
|
+
puts "Install directory: #{dir}"
|
26
|
+
|
27
|
+
# only needed if default path
|
28
|
+
FileUtils.mkdir_p(File.expand_path("../../tmp", __dir__)) unless ENV["CMDSTAN"]
|
29
|
+
|
30
|
+
if Dir.exist?(dir)
|
31
|
+
puts "Already installed"
|
32
|
+
return true
|
33
|
+
end
|
34
|
+
|
35
|
+
Dir.mktmpdir do |tmpdir|
|
36
|
+
puts "Downloading..."
|
37
|
+
download_path = File.join(tmpdir, "cmdstan-#{version}.tar.gz")
|
38
|
+
download_file(url, download_path, checksum)
|
39
|
+
|
40
|
+
puts "Unpacking..."
|
41
|
+
path = File.join(tmpdir, "cmdstan-#{version}")
|
42
|
+
FileUtils.mkdir_p(path)
|
43
|
+
tar_args = Gem.win_platform? ? ["--force-local"] : []
|
44
|
+
system "tar", "xzf", download_path, "-C", path, "--strip-components=1", *tar_args
|
45
|
+
|
46
|
+
puts "Building..."
|
47
|
+
make_command = Gem.win_platform? ? "mingw32-make" : "make"
|
48
|
+
Dir.chdir(path) do
|
49
|
+
# disable precompiled header to save space
|
50
|
+
output, status = Open3.capture2e(make_command, "build", "PRECOMPILED_HEADERS=false")
|
51
|
+
if status.exitstatus != 0
|
52
|
+
puts output
|
53
|
+
raise Error, "Build failed"
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
FileUtils.mv(path, dir)
|
58
|
+
end
|
59
|
+
|
60
|
+
puts "Installed"
|
61
|
+
|
62
|
+
true
|
63
|
+
end
|
64
|
+
|
65
|
+
private
|
66
|
+
|
67
|
+
def download_file(url, download_path, checksum, redirects = 0)
|
68
|
+
raise Error, "Too many redirects" if redirects > 10
|
69
|
+
|
70
|
+
uri = URI(url)
|
71
|
+
location = nil
|
72
|
+
|
73
|
+
Net::HTTP.start(uri.host, uri.port, use_ssl: true) do |http|
|
74
|
+
request = Net::HTTP::Get.new(uri)
|
75
|
+
http.request(request) do |response|
|
76
|
+
case response
|
77
|
+
when Net::HTTPRedirection
|
78
|
+
location = response["location"]
|
79
|
+
when Net::HTTPSuccess
|
80
|
+
digest = Digest::SHA2.new
|
81
|
+
|
82
|
+
File.open(download_path, "wb") do |f|
|
83
|
+
response.read_body do |chunk|
|
84
|
+
f.write(chunk)
|
85
|
+
digest.update(chunk)
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
raise Error, "Bad checksum: #{digest.hexdigest}" if digest.hexdigest != checksum
|
90
|
+
else
|
91
|
+
raise Error, "Bad response"
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
# outside of Net::HTTP block to close previous connection
|
97
|
+
download_file(location, download_path, checksum, redirects + 1) if location
|
98
|
+
end
|
99
|
+
end
|
100
|
+
end
|
data/lib/cmdstan/mcmc.rb
CHANGED
@@ -30,7 +30,7 @@ module CmdStan
|
|
30
30
|
run_command "#{CmdStan.path}/bin/stansummary#{extension}", "--csv_filename=#{path}", *@output_files.map(&:path)
|
31
31
|
|
32
32
|
result = {}
|
33
|
-
CSV.foreach(path, headers: true, converters: :numeric) do |row|
|
33
|
+
CSV.foreach(path, skip_lines: /^#/, headers: true, converters: :numeric) do |row|
|
34
34
|
value = row.to_h
|
35
35
|
name = value.delete("name")
|
36
36
|
result[name] = value if name == "lp__" || !name.end_with?("__")
|
data/lib/cmdstan/model.rb
CHANGED
@@ -18,8 +18,12 @@ module CmdStan
|
|
18
18
|
end
|
19
19
|
|
20
20
|
def compile
|
21
|
+
unless ENV["CMDSTAN"] || CmdStan.cmdstan_installed?
|
22
|
+
CmdStan.install_cmdstan
|
23
|
+
end
|
24
|
+
|
21
25
|
Dir.chdir(CmdStan.path) do
|
22
|
-
run_command make_command, @exe_file
|
26
|
+
run_command make_command, @exe_file, "PRECOMPILED_HEADERS=false"
|
23
27
|
end
|
24
28
|
end
|
25
29
|
|
@@ -32,7 +36,7 @@ module CmdStan
|
|
32
36
|
data_file.write(data.to_json)
|
33
37
|
data_file.close
|
34
38
|
|
35
|
-
|
39
|
+
chains ||= 4
|
36
40
|
|
37
41
|
output_files = []
|
38
42
|
chains.times do |chain|
|
data/lib/cmdstan/version.rb
CHANGED
data/lib/cmdstan.rb
CHANGED
@@ -1,10 +1,14 @@
|
|
1
1
|
# stdlib
|
2
|
+
require "digest"
|
2
3
|
require "csv"
|
4
|
+
require "fileutils"
|
3
5
|
require "json"
|
6
|
+
require "net/http"
|
4
7
|
require "open3"
|
5
8
|
require "tempfile"
|
6
9
|
|
7
10
|
# modules
|
11
|
+
require "cmdstan/install"
|
8
12
|
require "cmdstan/utils"
|
9
13
|
require "cmdstan/mcmc"
|
10
14
|
require "cmdstan/mle"
|
@@ -14,6 +18,8 @@ require "cmdstan/version"
|
|
14
18
|
module CmdStan
|
15
19
|
class Error < StandardError; end
|
16
20
|
|
21
|
+
extend Install
|
22
|
+
|
17
23
|
class << self
|
18
24
|
attr_accessor :path
|
19
25
|
end
|
metadata
CHANGED
@@ -1,28 +1,26 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: cmdstan
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1
|
4
|
+
version: 0.2.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Andrew Kane
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2022-
|
11
|
+
date: 2022-07-06 00:00:00.000000000 Z
|
12
12
|
dependencies: []
|
13
13
|
description:
|
14
14
|
email: andrew@ankane.org
|
15
15
|
executables: []
|
16
|
-
extensions:
|
17
|
-
- ext/cmdstan/extconf.rb
|
16
|
+
extensions: []
|
18
17
|
extra_rdoc_files: []
|
19
18
|
files:
|
20
19
|
- CHANGELOG.md
|
21
20
|
- LICENSE.txt
|
22
21
|
- README.md
|
23
|
-
- ext/cmdstan/Makefile
|
24
|
-
- ext/cmdstan/extconf.rb
|
25
22
|
- lib/cmdstan.rb
|
23
|
+
- lib/cmdstan/install.rb
|
26
24
|
- lib/cmdstan/mcmc.rb
|
27
25
|
- lib/cmdstan/mle.rb
|
28
26
|
- lib/cmdstan/model.rb
|
@@ -40,14 +38,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
40
38
|
requirements:
|
41
39
|
- - ">="
|
42
40
|
- !ruby/object:Gem::Version
|
43
|
-
version: '2.
|
41
|
+
version: '2.7'
|
44
42
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
45
43
|
requirements:
|
46
44
|
- - ">="
|
47
45
|
- !ruby/object:Gem::Version
|
48
46
|
version: '0'
|
49
47
|
requirements: []
|
50
|
-
rubygems_version: 3.3.
|
48
|
+
rubygems_version: 3.3.7
|
51
49
|
signing_key:
|
52
50
|
specification_version: 4
|
53
51
|
summary: Bayesian inference for Ruby, powered by CmdStan
|
data/ext/cmdstan/Makefile
DELETED
data/ext/cmdstan/extconf.rb
DELETED
@@ -1,68 +0,0 @@
|
|
1
|
-
require "digest"
|
2
|
-
require "fileutils"
|
3
|
-
require "net/http"
|
4
|
-
require "tmpdir"
|
5
|
-
|
6
|
-
version = "2.28.1"
|
7
|
-
checksum = "eacadb4a1ca6997c9858e301780e729e53a9b5207b19ae2616abc882677e7637"
|
8
|
-
url = "https://github.com/stan-dev/cmdstan/releases/download/v#{version}/cmdstan-#{version}.tar.gz"
|
9
|
-
|
10
|
-
path = ENV["CMDSTAN"] || File.expand_path("../../tmp/cmdstan", __dir__)
|
11
|
-
FileUtils.mkdir_p(path)
|
12
|
-
raise "Directory not empty. Run: rake clean" unless Dir.empty?(path)
|
13
|
-
|
14
|
-
$stdout.sync = true
|
15
|
-
|
16
|
-
def download_file(url, download_path, checksum, redirects = 0)
|
17
|
-
raise "Too many redirects" if redirects > 10
|
18
|
-
|
19
|
-
uri = URI(url)
|
20
|
-
location = nil
|
21
|
-
|
22
|
-
Net::HTTP.start(uri.host, uri.port, use_ssl: true) do |http|
|
23
|
-
request = Net::HTTP::Get.new(uri)
|
24
|
-
http.request(request) do |response|
|
25
|
-
case response
|
26
|
-
when Net::HTTPRedirection
|
27
|
-
location = response["location"]
|
28
|
-
when Net::HTTPSuccess
|
29
|
-
digest = Digest::SHA2.new
|
30
|
-
|
31
|
-
i = 0
|
32
|
-
File.open(download_path, "wb") do |f|
|
33
|
-
response.read_body do |chunk|
|
34
|
-
f.write(chunk)
|
35
|
-
digest.update(chunk)
|
36
|
-
|
37
|
-
# print progress
|
38
|
-
putc "." if i % 50 == 0
|
39
|
-
i += 1
|
40
|
-
end
|
41
|
-
end
|
42
|
-
puts # newline
|
43
|
-
|
44
|
-
abort "Bad checksum: #{digest.hexdigest}" if digest.hexdigest != checksum
|
45
|
-
else
|
46
|
-
abort "Bad response"
|
47
|
-
end
|
48
|
-
end
|
49
|
-
end
|
50
|
-
|
51
|
-
# outside of Net::HTTP block to close previous connection
|
52
|
-
download_file(location, download_path, checksum, redirects + 1) if location
|
53
|
-
end
|
54
|
-
|
55
|
-
# download
|
56
|
-
puts "Downloading #{url}..."
|
57
|
-
download_path = "#{Dir.tmpdir}/cmdstan-#{version}.tar.gz"
|
58
|
-
download_file(url, download_path, checksum)
|
59
|
-
|
60
|
-
# extract
|
61
|
-
Dir.chdir(path)
|
62
|
-
# TODO use Gem::Package::TarReader from Rubygems
|
63
|
-
tar_args = Gem.win_platform? ? ["--force-local"] : []
|
64
|
-
system "tar", "zxf", download_path, "-C", path, "--strip-components=1", *tar_args
|
65
|
-
|
66
|
-
# build
|
67
|
-
make_command = Gem.win_platform? ? "mingw32-make" : "make"
|
68
|
-
system make_command, "build"
|