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