1 | 'use strict';
|
2 |
|
3 | Object.defineProperty(exports, "__esModule", {
|
4 | value: true
|
5 | });
|
6 | exports.randint = randint;
|
7 | exports.rand = rand;
|
8 | exports.sampleFisherYates = sampleFisherYates;
|
9 | exports.sample = sample;
|
10 |
|
11 | var _arrays = require('../arrays');
|
12 |
|
13 | var Arrays = _interopRequireWildcard(_arrays);
|
14 |
|
15 | var _search = require('../util/search');
|
16 |
|
17 | var Search = _interopRequireWildcard(_search);
|
18 |
|
19 | function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } }
|
20 |
|
21 | function _toConsumableArray(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } else { return Array.from(arr); } }
|
22 |
|
23 |
|
24 |
|
25 |
|
26 |
|
27 |
|
28 |
|
29 |
|
30 |
|
31 |
|
32 |
|
33 |
|
34 |
|
35 |
|
36 |
|
37 | function randint(a, b) {
|
38 | var shape = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : null;
|
39 |
|
40 | if (Number.isInteger(shape)) {
|
41 |
|
42 | return [].concat(_toConsumableArray(Array(shape))).map(function (x) {
|
43 | return randint(a, b);
|
44 | });
|
45 | } else if (Array.isArray(shape) && shape.length > 0) {
|
46 | if (shape.length === 1) {
|
47 |
|
48 | return randint(a, b, shape[0]);
|
49 | }
|
50 |
|
51 |
|
52 | return [].concat(_toConsumableArray(Array(shape[0]))).map(function () {
|
53 | return randint(a, b, shape.slice(1));
|
54 | });
|
55 | }
|
56 |
|
57 |
|
58 | return a + Math.floor((b - a) * Math.random());
|
59 | }
|
60 |
|
61 |
|
62 |
|
63 |
|
64 |
|
65 |
|
66 |
|
67 |
|
68 | function rand(a, b) {
|
69 | return a + Math.random() * (b - a);
|
70 | }
|
71 |
|
72 |
|
73 |
|
74 |
|
75 |
|
76 |
|
77 |
|
78 |
|
79 |
|
80 | function sampleFisherYates(input, number) {
|
81 |
|
82 | var shuffledArray = input.slice(0);
|
83 |
|
84 |
|
85 | var numElements = input.length;
|
86 |
|
87 | for (var i = numElements - 1; i >= numElements - number; i -= 1) {
|
88 | var index = randint(0, i + 1);
|
89 | var tmp = shuffledArray[index];
|
90 | shuffledArray[index] = shuffledArray[i];
|
91 | shuffledArray[i] = tmp;
|
92 | }
|
93 |
|
94 |
|
95 | return shuffledArray.slice(numElements - number);
|
96 | }
|
97 |
|
98 |
|
99 |
|
100 |
|
101 |
|
102 |
|
103 |
|
104 |
|
105 |
|
106 |
|
107 | function sampleUniform(input, number) {
|
108 | var withReplacement = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : true;
|
109 |
|
110 |
|
111 | if (!withReplacement) {
|
112 | return sampleFisherYates(input, number);
|
113 | }
|
114 |
|
115 |
|
116 | var indices = randint(0, input.length, number);
|
117 | return indices.map(function (x) {
|
118 | return input[x];
|
119 | });
|
120 | }
|
121 |
|
122 |
|
123 |
|
124 |
|
125 |
|
126 |
|
127 |
|
128 |
|
129 |
|
130 |
|
131 |
|
132 |
|
133 |
|
134 |
|
135 | function sample(input, number) {
|
136 | var withReplacement = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : true;
|
137 | var weights = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : 'uniform';
|
138 |
|
139 | if (Array.isArray(weights)) {
|
140 | if (weights.length !== input.length) {
|
141 | throw new Error('Weights array length does not equal input array length.');
|
142 | }
|
143 |
|
144 | if (!withReplacement && number > weights.filter(function (x) {
|
145 | return x > 0;
|
146 | }).length) {
|
147 | throw new Error('Invalid sampling quantity specified: sampling without replacement cannot sample more elements than the number of non-zero weights in the weights array.');
|
148 | }
|
149 | } else if (weights !== 'uniform') {
|
150 | throw new Error('Invalid value specified for "weights".');
|
151 | }
|
152 |
|
153 | if (!withReplacement && number > input.length) {
|
154 | throw new Error('Invalid sampling quantity specified: sampling without replacement cannot sample more elements than the number of input elements.');
|
155 | }
|
156 |
|
157 |
|
158 | if (weights === 'uniform') {
|
159 | return sampleUniform(input, number, withReplacement);
|
160 | }
|
161 |
|
162 |
|
163 | var useWeights = weights.slice();
|
164 |
|
165 | var calculateCumWeights = function calculateCumWeights(localWeights) {
|
166 | return localWeights.reduce(function (r, a, i) {
|
167 | return [].concat(_toConsumableArray(r), [i > 0 ? r[i - 1] + a : a]);
|
168 | }, []);
|
169 | };
|
170 |
|
171 | var sampleSingle = function sampleSingle(useCumWeights) {
|
172 |
|
173 |
|
174 |
|
175 | var randomNumber = rand(0, useCumWeights[useCumWeights.length - 1]);
|
176 | return Search.binaryIntervalSearch([0].concat(_toConsumableArray(useCumWeights)), randomNumber);
|
177 | };
|
178 |
|
179 | if (withReplacement) {
|
180 |
|
181 | var cumWeights = calculateCumWeights(useWeights);
|
182 |
|
183 | return Arrays.zeros(number).map(function () {
|
184 | return input[sampleSingle(cumWeights)];
|
185 | });
|
186 | }
|
187 |
|
188 |
|
189 |
|
190 |
|
191 |
|
192 | var useInput = input.slice();
|
193 |
|
194 |
|
195 | var samples = [];
|
196 |
|
197 | while (samples.length < number) {
|
198 |
|
199 | var _cumWeights = calculateCumWeights(useWeights);
|
200 | var useSample = sampleSingle(_cumWeights);
|
201 | samples.push(useInput[useSample]);
|
202 |
|
203 |
|
204 | useInput.splice(useSample, 1);
|
205 | useWeights.splice(useSample, 1);
|
206 | }
|
207 |
|
208 | return samples;
|
209 | } |
\ | No newline at end of file |