{"action":"created","comment":{"url":"https://api.github.com/repos/gonum/stat/pulls/comments/50796368","id":50796368,"diff_hunk":"@@ -0,0 +1,281 @@\n+// Copyright ©2016 The gonum Authors. All rights reserved.\n+// Use of this source code is governed by a BSD-style\n+// license that can be found in the LICENSE file.\n+\n+// Package samplemv implements advanced sampling routines from explicit and implicit\n+// probability distributions.\n+//\n+// Each sampling routine is implemented as a stateless function with a\n+// complementary wrapper type. The wrapper types allow the sampling routines\n+// to implement interfaces.\n+package samplemv\n+\n+import (\n+\t\"errors\"\n+\t\"math\"\n+\t\"math/rand\"\n+\n+\t\"github.com/gonum/matrix/mat64\"\n+\t\"github.com/gonum/stat/distmv\"\n+)\n+\n+var (\n+\tbadLengthMismatch = \"sample: slice length mismatch\"\n+)\n+\n+var (\n+\t_ Sampler = LatinHypercuber{}\n+\t_ Sampler = (*Rejectioner)(nil)\n+\t_ Sampler = IIDer{}\n+\n+\t_ WeightedSampler = SampleUniformWeighted{}\n+\t_ WeightedSampler = Importancer{}\n+)\n+\n+func min(a, b int) int {\n+\tif a < b {\n+\t\treturn a\n+\t}\n+\treturn b\n+}\n+\n+// Sampler generates a batch of samples according to the rule specified by the\n+// implementing type. The number of samples generated is equal to rows(batch),\n+// and the samples are stored in-place into the input.\n+type Sampler interface {\n+\tSample(batch *mat64.Dense)\n+}\n+\n+// WeightedSampler generates a batch of samples and their relative weights\n+// according to the rule specified by the implementing type. The number of samples\n+// generated is equal to rows(batch), and the samples and weights\n+// are stored in-place into the inputs. The length of weights must equal\n+// rows(batch), otherwise the WeightedSampler will panic.\n+type WeightedSampler interface {\n+\tSampleWeighted(batch *mat64.Dense, weights []float64)\n+}\n+\n+// SampleUniformWeighted wraps a Sampler type to create a WeightedSampler where all\n+// weights are equal.\n+type SampleUniformWeighted struct {\n+\tSampler\n+}\n+\n+// SampleWeighted generates rows(batch) samples from the embedded Sampler type\n+// and sets all of the weights equal to 1. If rows(batch) and len(weights)\n+// of weights are not equal, SampleWeighted will panic.\n+func (w SampleUniformWeighted) SampleWeighted(batch *mat64.Dense, weights []float64) {\n+\tr, _ := batch.Dims()\n+\tif r != len(weights) {\n+\t\tpanic(badLengthMismatch)\n+\t}\n+\tw.Sample(batch)\n+\tfor i := range weights {\n+\t\tweights[i] = 1\n+\t}\n+}\n+\n+// LatinHypercuber is a wrapper around the LatinHypercube sampling generation\n+// method.\n+type LatinHypercuber struct {\n+\tQ   distmv.Quantiler\n+\tSrc *rand.Rand\n+}\n+\n+// Sample generates rows(batch) samples using the LatinHypercube generation\n+// procedure.\n+func (l LatinHypercuber) Sample(batch *mat64.Dense) {\n+\tLatinHypercube(batch, l.Q, l.Src)\n+}\n+\n+// LatinHypercube generates rows(batch) samples using Latin hypercube sampling\n+// from the given distribution. If src != nil, it will be used to generate\n+// random numbers, otherwise rand.Float64 will be used.\n+//\n+// Latin hypercube sampling divides the cumulative distribution function into equally\n+// spaced bins and guarantees that one sample is generated per bin. Within each bin,\n+// the location is randomly sampled. The distmv.UnitNormal variable can be used\n+// for easy generation from the unit interval.\n+func LatinHypercube(batch *mat64.Dense, q distmv.Quantiler, src *rand.Rand) {\n+\tr, c := batch.Dims()\n+\tvar f64 func() float64\n+\tvar perm func(int) []int\n+\tif src != nil {\n+\t\tf64 = src.Float64\n+\t\tperm = src.Perm\n+\t} else {\n+\t\tf64 = rand.Float64\n+\t\tperm = rand.Perm\n+\t}\n+\tr64 := float64(r)\n+\tfor i := 0; i < c; i++ {\n+\t\tp := perm(r)\n+\t\tfor j := 0; j < r; j++ {\n+\t\t\tvar v float64\n+\t\t\tv = f64()\n+\t\t\tv = v/r64 + float64(j)/r64\n+\t\t\tbatch.Set(p[j], i, v)\n+\t\t}\n+\t}\n+\tp := make([]float64, c)\n+\tfor i := 0; i < r; i++ {\n+\t\tcopy(p, batch.RawRowView(i))\n+\t\tq.Quantile(batch.RawRowView(i), p)\n+\t}\n+}\n+\n+// Importancer is a wrapper around the Importance sampling generation method.\n+type Importancer struct {\n+\tTarget   distmv.LogProber\n+\tProposal distmv.RandLogProber\n+}\n+\n+// Sample generates rows(batch) samples using the Importance sampling generation\n+// procedure.\n+func (l Importancer) SampleWeighted(batch *mat64.Dense, weights []float64) {\n+\tImportance(batch, weights, l.Target, l.Proposal)\n+}\n+\n+// Importance sampling generates rows(batch) samples from the proposal distribution,\n+// and stores the locations and importance sampling weights in place.\n+//\n+// Importance sampling is a variance reduction technique where samples are\n+// generated from a proposal distribution, q(x), instead of the target distribution\n+// p(x). This allows relatively unlikely samples in p(x) to be generated more frequently\n+//\n+// The importance sampling weight at x is given by p(x)/q(x). To reduce variance,\n+// a good proposal distribution will bound this sampling weight. This implies the\n+// support of q(x) should be at least as broad as p(x), and q(x) should be \"fatter tailed\"\n+// than p(x).\n+//\n+// If weights is nil the weights are not stored. The length of weights must equal\n+// the length of batch, otherwise Importance will panic.\n+func Importance(batch *mat64.Dense, weights []float64, target distmv.LogProber, proposal distmv.RandLogProber) {\n+\tr, _ := batch.Dims()\n+\tif r != len(weights) {\n+\t\tpanic(badLengthMismatch)\n+\t}\n+\tfor i := 0; i < r; i++ {\n+\t\tv := batch.RawRowView(i)\n+\t\tproposal.Rand(v)\n+\t\tweights[i] = math.Exp(target.LogProb(v) - proposal.LogProb(v))\n+\t}\n+}\n+\n+var ErrRejection = errors.New(\"rejection: acceptance ratio above 1\")\n+\n+// Rejectioner is a wrapper around the Rejection sampling generation procedure.\n+// If the rejection sampling fails during the call to Sample, all samples will\n+// be set to math.NaN() and a call to Err will return a non-nil value.\n+type Rejectioner struct {\n+\tC        float64\n+\tTarget   distmv.LogProber\n+\tProposal distmv.RandLogProber\n+\tSrc      *rand.Rand\n+\n+\terr      error\n+\tproposed int\n+}\n+\n+// Err returns nil if the most recent call to sample was successful, and returns\n+// ErrRejection if it was not.\n+func (r *Rejectioner) Err() error {\n+\treturn r.err\n+}\n+\n+// Proposed returns the number of samples proposed during the most recent call to\n+// Sample.\n+func (r *Rejectioner) Proposed() int {\n+\treturn r.proposed\n+}\n+\n+// Sample generates rows(batch) using the Rejection sampling generation procedure.\n+// Rejection sampling may fail if the constant is insufficiently high, as described\n+// in the function comment for Rejection. If the generation fails, the samples\n+// are set to math.NaN(), and a call to Err will return a non-nil value.\n+func (r *Rejectioner) Sample(batch *mat64.Dense) {\n+\tr.err = nil\n+\tr.proposed = 0\n+\tproposed, ok := Rejection(batch, r.Target, r.Proposal, r.C, r.Src)\n+\tif !ok {\n+\t\tr.err = ErrRejection\n+\t}\n+\tr.proposed = proposed\n+}\n+\n+// Rejection generates rows(batch) samples using the rejection sampling algorithm and\n+// stores them in place into samples.\n+// Sampling continues until batch is filled. Rejection returns the total number of proposed","path":"samplemv/samplemv.go","position":208,"original_position":208,"commit_id":"c2fa6a970b14abe84ca1af237b2711a390459dda","original_commit_id":"c2fa6a970b14abe84ca1af237b2711a390459dda","user":{"login":"btracey","id":3680859,"avatar_url":"https://avatars.githubusercontent.com/u/3680859?v=3","gravatar_id":"","url":"https://api.github.com/users/btracey","html_url":"https://github.com/btracey","followers_url":"https://api.github.com/users/btracey/followers","following_url":"https://api.github.com/users/btracey/following{/other_user}","gists_url":"https://api.github.com/users/btracey/gists{/gist_id}","starred_url":"https://api.github.com/users/btracey/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/btracey/subscriptions","organizations_url":"https://api.github.com/users/btracey/orgs","repos_url":"https://api.github.com/users/btracey/repos","events_url":"https://api.github.com/users/btracey/events{/privacy}","received_events_url":"https://api.github.com/users/btracey/received_events","type":"User","site_admin":false},"body":"Done.","created_at":"2016-01-26T05:17:29Z","updated_at":"2016-01-26T05:17:29Z","html_url":"https://github.com/gonum/stat/pull/77#discussion_r50796368","pull_request_url":"https://api.github.com/repos/gonum/stat/pulls/77","_links":{"self":{"href":"https://api.github.com/repos/gonum/stat/pulls/comments/50796368"},"html":{"href":"https://github.com/gonum/stat/pull/77#discussion_r50796368"},"pull_request":{"href":"https://api.github.com/repos/gonum/stat/pulls/77"}}},"pull_request":{"url":"https://api.github.com/repos/gonum/stat/pulls/77","id":57011650,"html_url":"https://github.com/gonum/stat/pull/77","diff_url":"https://github.com/gonum/stat/pull/77.diff","patch_url":"https://github.com/gonum/stat/pull/77.patch","issue_url":"https://api.github.com/repos/gonum/stat/issues/77","number":77,"state":"open","locked":false,"title":"Add samplemv package, auxiliary functions, and tests","user":{"login":"btracey","id":3680859,"avatar_url":"https://avatars.githubusercontent.com/u/3680859?v=3","gravatar_id":"","url":"https://api.github.com/users/btracey","html_url":"https://github.com/btracey","followers_url":"https://api.github.com/users/btracey/followers","following_url":"https://api.github.com/users/btracey/following{/other_user}","gists_url":"https://api.github.com/users/btracey/gists{/gist_id}","starred_url":"https://api.github.com/users/btracey/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/btracey/subscriptions","organizations_url":"https://api.github.com/users/btracey/orgs","repos_url":"https://api.github.com/users/btracey/repos","events_url":"https://api.github.com/users/btracey/events{/privacy}","received_events_url":"https://api.github.com/users/btracey/received_events","type":"User","site_admin":false},"body":"","created_at":"2016-01-24T19:43:51Z","updated_at":"2016-01-26T05:17:29Z","closed_at":null,"merged_at":null,"merge_commit_sha":"8156d48224e23eef25522905964bfa3dbac83278","assignee":null,"milestone":null,"commits_url":"https://api.github.com/repos/gonum/stat/pulls/77/commits","review_comments_url":"https://api.github.com/repos/gonum/stat/pulls/77/comments","review_comment_url":"https://api.github.com/repos/gonum/stat/pulls/comments{/number}","comments_url":"https://api.github.com/repos/gonum/stat/issues/77/comments","statuses_url":"https://api.github.com/repos/gonum/stat/statuses/c2fa6a970b14abe84ca1af237b2711a390459dda","head":{"label":"gonum:addsamplemv","ref":"addsamplemv","sha":"c2fa6a970b14abe84ca1af237b2711a390459dda","user":{"login":"gonum","id":3771091,"avatar_url":"https://avatars.githubusercontent.com/u/3771091?v=3","gravatar_id":"","url":"https://api.github.com/users/gonum","html_url":"https://github.com/gonum","followers_url":"https://api.github.com/users/gonum/followers","following_url":"https://api.github.com/users/gonum/following{/other_user}","gists_url":"https://api.github.com/users/gonum/gists{/gist_id}","starred_url":"https://api.github.com/users/gonum/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/gonum/subscriptions","organizations_url":"https://api.github.com/users/gonum/orgs","repos_url":"https://api.github.com/users/gonum/repos","events_url":"https://api.github.com/users/gonum/events{/privacy}","received_events_url":"https://api.github.com/users/gonum/received_events","type":"Organization","site_admin":false},"repo":{"id":22622955,"name":"stat","full_name":"gonum/stat","owner":{"login":"gonum","id":3771091,"avatar_url":"https://avatars.githubusercontent.com/u/3771091?v=3","gravatar_id":"","url":"https://api.github.com/users/gonum","html_url":"https://github.com/gonum","followers_url":"https://api.github.com/users/gonum/followers","following_url":"https://api.github.com/users/gonum/following{/other_user}","gists_url":"https://api.github.com/users/gonum/gists{/gist_id}","starred_url":"https://api.github.com/users/gonum/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/gonum/subscriptions","organizations_url":"https://api.github.com/users/gonum/orgs","repos_url":"https://api.github.com/users/gonum/repos","events_url":"https://api.github.com/users/gonum/events{/privacy}","received_events_url":"https://api.github.com/users/gonum/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/gonum/stat","description":"Statistics package for Go","fork":false,"url":"https://api.github.com/repos/gonum/stat","forks_url":"https://api.github.com/repos/gonum/stat/forks","keys_url":"https://api.github.com/repos/gonum/stat/keys{/key_id}","collaborators_url":"https://api.github.com/repos/gonum/stat/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/gonum/stat/teams","hooks_url":"https://api.github.com/repos/gonum/stat/hooks","issue_events_url":"https://api.github.com/repos/gonum/stat/issues/events{/number}","events_url":"https://api.github.com/repos/gonum/stat/events","assignees_url":"https://api.github.com/repos/gonum/stat/assignees{/user}","branches_url":"https://api.github.com/repos/gonum/stat/branches{/branch}","tags_url":"https://api.github.com/repos/gonum/stat/tags","blobs_url":"https://api.github.com/repos/gonum/stat/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/gonum/stat/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/gonum/stat/git/refs{/sha}","trees_url":"https://api.github.com/repos/gonum/stat/git/trees{/sha}","statuses_url":"https://api.github.com/repos/gonum/stat/statuses/{sha}","languages_url":"https://api.github.com/repos/gonum/stat/languages","stargazers_url":"https://api.github.com/repos/gonum/stat/stargazers","contributors_url":"https://api.github.com/repos/gonum/stat/contributors","subscribers_url":"https://api.github.com/repos/gonum/stat/subscribers","subscription_url":"https://api.github.com/repos/gonum/stat/subscription","commits_url":"https://api.github.com/repos/gonum/stat/commits{/sha}","git_commits_url":"https://api.github.com/repos/gonum/stat/git/commits{/sha}","comments_url":"https://api.github.com/repos/gonum/stat/comments{/number}","issue_comment_url":"https://api.github.com/repos/gonum/stat/issues/comments{/number}","contents_url":"https://api.github.com/repos/gonum/stat/contents/{+path}","compare_url":"https://api.github.com/repos/gonum/stat/compare/{base}...{head}","merges_url":"https://api.github.com/repos/gonum/stat/merges","archive_url":"https://api.github.com/repos/gonum/stat/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/gonum/stat/downloads","issues_url":"https://api.github.com/repos/gonum/stat/issues{/number}","pulls_url":"https://api.github.com/repos/gonum/stat/pulls{/number}","milestones_url":"https://api.github.com/repos/gonum/stat/milestones{/number}","notifications_url":"https://api.github.com/repos/gonum/stat/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/gonum/stat/labels{/name}","releases_url":"https://api.github.com/repos/gonum/stat/releases{/id}","deployments_url":"https://api.github.com/repos/gonum/stat/deployments","created_at":"2014-08-04T23:07:41Z","updated_at":"2016-01-15T20:33:52Z","pushed_at":"2016-01-26T00:01:37Z","git_url":"git://github.com/gonum/stat.git","ssh_url":"git@github.com:gonum/stat.git","clone_url":"https://github.com/gonum/stat.git","svn_url":"https://github.com/gonum/stat","homepage":"","size":357,"stargazers_count":59,"watchers_count":59,"language":"Go","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":11,"mirror_url":null,"open_issues_count":13,"forks":11,"open_issues":13,"watchers":59,"default_branch":"master"}},"base":{"label":"gonum:master","ref":"master","sha":"c8e775add880f94c9afb4a09ce71bcc6c98f52ee","user":{"login":"gonum","id":3771091,"avatar_url":"https://avatars.githubusercontent.com/u/3771091?v=3","gravatar_id":"","url":"https://api.github.com/users/gonum","html_url":"https://github.com/gonum","followers_url":"https://api.github.com/users/gonum/followers","following_url":"https://api.github.com/users/gonum/following{/other_user}","gists_url":"https://api.github.com/users/gonum/gists{/gist_id}","starred_url":"https://api.github.com/users/gonum/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/gonum/subscriptions","organizations_url":"https://api.github.com/users/gonum/orgs","repos_url":"https://api.github.com/users/gonum/repos","events_url":"https://api.github.com/users/gonum/events{/privacy}","received_events_url":"https://api.github.com/users/gonum/received_events","type":"Organization","site_admin":false},"repo":{"id":22622955,"name":"stat","full_name":"gonum/stat","owner":{"login":"gonum","id":3771091,"avatar_url":"https://avatars.githubusercontent.com/u/3771091?v=3","gravatar_id":"","url":"https://api.github.com/users/gonum","html_url":"https://github.com/gonum","followers_url":"https://api.github.com/users/gonum/followers","following_url":"https://api.github.com/users/gonum/following{/other_user}","gists_url":"https://api.github.com/users/gonum/gists{/gist_id}","starred_url":"https://api.github.com/users/gonum/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/gonum/subscriptions","organizations_url":"https://api.github.com/users/gonum/orgs","repos_url":"https://api.github.com/users/gonum/repos","events_url":"https://api.github.com/users/gonum/events{/privacy}","received_events_url":"https://api.github.com/users/gonum/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/gonum/stat","description":"Statistics package for Go","fork":false,"url":"https://api.github.com/repos/gonum/stat","forks_url":"https://api.github.com/repos/gonum/stat/forks","keys_url":"https://api.github.com/repos/gonum/stat/keys{/key_id}","collaborators_url":"https://api.github.com/repos/gonum/stat/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/gonum/stat/teams","hooks_url":"https://api.github.com/repos/gonum/stat/hooks","issue_events_url":"https://api.github.com/repos/gonum/stat/issues/events{/number}","events_url":"https://api.github.com/repos/gonum/stat/events","assignees_url":"https://api.github.com/repos/gonum/stat/assignees{/user}","branches_url":"https://api.github.com/repos/gonum/stat/branches{/branch}","tags_url":"https://api.github.com/repos/gonum/stat/tags","blobs_url":"https://api.github.com/repos/gonum/stat/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/gonum/stat/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/gonum/stat/git/refs{/sha}","trees_url":"https://api.github.com/repos/gonum/stat/git/trees{/sha}","statuses_url":"https://api.github.com/repos/gonum/stat/statuses/{sha}","languages_url":"https://api.github.com/repos/gonum/stat/languages","stargazers_url":"https://api.github.com/repos/gonum/stat/stargazers","contributors_url":"https://api.github.com/repos/gonum/stat/contributors","subscribers_url":"https://api.github.com/repos/gonum/stat/subscribers","subscription_url":"https://api.github.com/repos/gonum/stat/subscription","commits_url":"https://api.github.com/repos/gonum/stat/commits{/sha}","git_commits_url":"https://api.github.com/repos/gonum/stat/git/commits{/sha}","comments_url":"https://api.github.com/repos/gonum/stat/comments{/number}","issue_comment_url":"https://api.github.com/repos/gonum/stat/issues/comments{/number}","contents_url":"https://api.github.com/repos/gonum/stat/contents/{+path}","compare_url":"https://api.github.com/repos/gonum/stat/compare/{base}...{head}","merges_url":"https://api.github.com/repos/gonum/stat/merges","archive_url":"https://api.github.com/repos/gonum/stat/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/gonum/stat/downloads","issues_url":"https://api.github.com/repos/gonum/stat/issues{/number}","pulls_url":"https://api.github.com/repos/gonum/stat/pulls{/number}","milestones_url":"https://api.github.com/repos/gonum/stat/milestones{/number}","notifications_url":"https://api.github.com/repos/gonum/stat/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/gonum/stat/labels{/name}","releases_url":"https://api.github.com/repos/gonum/stat/releases{/id}","deployments_url":"https://api.github.com/repos/gonum/stat/deployments","created_at":"2014-08-04T23:07:41Z","updated_at":"2016-01-15T20:33:52Z","pushed_at":"2016-01-26T00:01:37Z","git_url":"git://github.com/gonum/stat.git","ssh_url":"git@github.com:gonum/stat.git","clone_url":"https://github.com/gonum/stat.git","svn_url":"https://github.com/gonum/stat","homepage":"","size":357,"stargazers_count":59,"watchers_count":59,"language":"Go","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":11,"mirror_url":null,"open_issues_count":13,"forks":11,"open_issues":13,"watchers":59,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/gonum/stat/pulls/77"},"html":{"href":"https://github.com/gonum/stat/pull/77"},"issue":{"href":"https://api.github.com/repos/gonum/stat/issues/77"},"comments":{"href":"https://api.github.com/repos/gonum/stat/issues/77/comments"},"review_comments":{"href":"https://api.github.com/repos/gonum/stat/pulls/77/comments"},"review_comment":{"href":"https://api.github.com/repos/gonum/stat/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/gonum/stat/pulls/77/commits"},"statuses":{"href":"https://api.github.com/repos/gonum/stat/statuses/c2fa6a970b14abe84ca1af237b2711a390459dda"}}}}