Init
This commit is contained in:
parent
1684d79d9b
commit
531df57242
|
@ -55,7 +55,10 @@
|
||||||
"react-dom": "16.12.0",
|
"react-dom": "16.12.0",
|
||||||
"reason-react": ">=0.7.0",
|
"reason-react": ">=0.7.0",
|
||||||
"reschema": "1.3.0",
|
"reschema": "1.3.0",
|
||||||
"tailwindcss": "1.2.0"
|
"tailwindcss": "1.2.0",
|
||||||
|
"binary-search-tree": "0.2.6",
|
||||||
|
"jstat": "1.9.2",
|
||||||
|
"mathjs": "6.6.0"
|
||||||
},
|
},
|
||||||
"alias": {
|
"alias": {
|
||||||
"react": "./node_modules/react",
|
"react": "./node_modules/react",
|
||||||
|
|
181
src/components/editor/distribution.js
Normal file
181
src/components/editor/distribution.js
Normal file
|
@ -0,0 +1,181 @@
|
||||||
|
// This module defines an abstract BinnedDistribution class, which
|
||||||
|
// should be implemented for each distribution. You need to decide
|
||||||
|
// how to bin the distribution (use _adabin unless there's a nicer
|
||||||
|
// way for your distr) and how to choose the distribution's support.
|
||||||
|
const _math = require("mathjs");
|
||||||
|
const math = _math.create(_math.all);
|
||||||
|
const jStat = require("jstat");
|
||||||
|
|
||||||
|
math.import({
|
||||||
|
normal: jStat.normal,
|
||||||
|
beta: jStat.beta,
|
||||||
|
lognormal: jStat.lognormal,
|
||||||
|
uniform: jStat.uniform
|
||||||
|
});
|
||||||
|
|
||||||
|
class BaseDistributionBinned {
|
||||||
|
constructor(args) {
|
||||||
|
this._set_props();
|
||||||
|
this.max_bin_size = 0.5;
|
||||||
|
this.min_bin_size = 0;
|
||||||
|
this.increment = 0.001;
|
||||||
|
this.desired_delta = 0.01;
|
||||||
|
this.start_bin_size = 0.01;
|
||||||
|
|
||||||
|
[this.params, this.pdf_func, this.sample] = this.get_params_and_pdf_func(
|
||||||
|
args
|
||||||
|
);
|
||||||
|
|
||||||
|
[this.start_point, this.end_point] = this.get_bounds();
|
||||||
|
[this.pdf_vals, this.divider_pts] = this.bin();
|
||||||
|
}
|
||||||
|
|
||||||
|
_set_props() {
|
||||||
|
// this is hacky but class properties aren't always supported
|
||||||
|
throw new Error("NotImplementedError");
|
||||||
|
}
|
||||||
|
|
||||||
|
_adabin() {
|
||||||
|
let point = this.start_point;
|
||||||
|
let vals = [this.pdf_func(point)];
|
||||||
|
let divider_pts = [point];
|
||||||
|
let support = this.end_point - this.start_point;
|
||||||
|
let bin_size = this.start_bin_size * support;
|
||||||
|
|
||||||
|
while (point < this.end_point) {
|
||||||
|
let val = this.pdf_func(point + bin_size);
|
||||||
|
if (Math.abs(val - vals[vals.length - 1]) > this.desired_delta) {
|
||||||
|
while (
|
||||||
|
(Math.abs(val - vals[vals.length - 1]) > this.desired_delta) &
|
||||||
|
(bin_size - this.increment * support > this.min_bin_size)
|
||||||
|
) {
|
||||||
|
bin_size -= this.increment;
|
||||||
|
val = this.pdf_func(point + bin_size);
|
||||||
|
}
|
||||||
|
} else if (Math.abs(val - vals[vals.length - 1]) < this.desired_delta) {
|
||||||
|
while (
|
||||||
|
(Math.abs(val - vals[vals.length - 1]) < this.desired_delta) &
|
||||||
|
(bin_size < this.max_bin_size)
|
||||||
|
) {
|
||||||
|
bin_size += this.increment;
|
||||||
|
val = this.pdf_func(point + bin_size);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
point += bin_size;
|
||||||
|
vals.push(val);
|
||||||
|
divider_pts.push(point);
|
||||||
|
}
|
||||||
|
vals = vals.map((_, idx) => vals[idx] / 2 + vals[idx + 1] / 2);
|
||||||
|
vals = vals.slice(0, -1);
|
||||||
|
return [vals, divider_pts];
|
||||||
|
}
|
||||||
|
|
||||||
|
bin() {
|
||||||
|
throw new Error("NotImplementedError");
|
||||||
|
}
|
||||||
|
|
||||||
|
get_bounds() {
|
||||||
|
throw new Error("NotImplementedError");
|
||||||
|
}
|
||||||
|
|
||||||
|
get_params_and_pdf_func(args) {
|
||||||
|
let args_str = args.toString() + ")";
|
||||||
|
let substr = this.name + ".pdf(x, " + args_str;
|
||||||
|
let compiled = math.compile(substr);
|
||||||
|
function pdf_func(x) {
|
||||||
|
return compiled.evaluate({ x: x });
|
||||||
|
}
|
||||||
|
let mc_compiled = math.compile(this.name + ".sample(" + args_str);
|
||||||
|
let kv_pairs = this.param_names.map((val, idx) => [val, args[idx]]);
|
||||||
|
let params = Object.fromEntries(new Map(kv_pairs));
|
||||||
|
return [params, pdf_func, mc_compiled.evaluate];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class NormalDistributionBinned extends BaseDistributionBinned {
|
||||||
|
_set_props() {
|
||||||
|
this.name = "normal";
|
||||||
|
this.param_names = ["mean", "std"];
|
||||||
|
}
|
||||||
|
get_bounds() {
|
||||||
|
return [
|
||||||
|
this.params.mean - 4 * this.params.std,
|
||||||
|
this.params.mean + 4 * this.params.std
|
||||||
|
];
|
||||||
|
}
|
||||||
|
bin() {
|
||||||
|
return this._adabin(this.params.std);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class UniformDistributionBinned extends BaseDistributionBinned {
|
||||||
|
_set_props() {
|
||||||
|
this.name = "uniform";
|
||||||
|
this.param_names = ["start_point", "end_point"];
|
||||||
|
this.num_bins = 200;
|
||||||
|
}
|
||||||
|
get_bounds() {
|
||||||
|
return [this.params.start_point, this.params.end_point];
|
||||||
|
}
|
||||||
|
bin() {
|
||||||
|
let divider_pts = evenly_spaced_grid(
|
||||||
|
this.params.start_point,
|
||||||
|
this.params.end_point,
|
||||||
|
this.num_bins
|
||||||
|
);
|
||||||
|
let vals = divider_pts.map(x =>
|
||||||
|
this.pdf_func(this.params.start_point / 2 + this.params.end_point / 2)
|
||||||
|
);
|
||||||
|
vals = vals.slice(0, -1);
|
||||||
|
return [vals, divider_pts];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class LogNormalDistributionBinned extends BaseDistributionBinned {
|
||||||
|
_set_props() {
|
||||||
|
this.name = "lognormal";
|
||||||
|
this.param_names = ["normal_mean", "normal_std"];
|
||||||
|
this.n_bounds_samples = 1000;
|
||||||
|
this.n_largest_bound_sample = 10;
|
||||||
|
}
|
||||||
|
|
||||||
|
_nth_largest(samples, n) {
|
||||||
|
var largest_buffer = Array(n).fill(-Infinity);
|
||||||
|
for (const sample of samples) {
|
||||||
|
if (sample > largest_buffer[n - 1]) {
|
||||||
|
var i = n;
|
||||||
|
while ((i > 0) & (sample > largest_buffer[i - 1])) {
|
||||||
|
i -= 1;
|
||||||
|
}
|
||||||
|
largest_buffer[i] = sample;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return largest_buffer[n - 1];
|
||||||
|
}
|
||||||
|
get_bounds() {
|
||||||
|
let samples = Array(this.n_bounds_samples)
|
||||||
|
.fill(0)
|
||||||
|
.map(() => this.sample());
|
||||||
|
return [
|
||||||
|
math.min(samples),
|
||||||
|
this._nth_largest(samples, this.n_largest_bound_sample)
|
||||||
|
];
|
||||||
|
}
|
||||||
|
bin() {
|
||||||
|
return this._adabin();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function evenly_spaced_grid(start, stop, numel) {
|
||||||
|
return Array(numel)
|
||||||
|
.fill(0)
|
||||||
|
.map((_, idx) => start + (idx / numel) * (stop - start));
|
||||||
|
}
|
||||||
|
|
||||||
|
const distrs = {
|
||||||
|
normal: NormalDistributionBinned,
|
||||||
|
lognormal: LogNormalDistributionBinned,
|
||||||
|
uniform: UniformDistributionBinned
|
||||||
|
};
|
||||||
|
|
||||||
|
exports.distrs = distrs;
|
31
src/components/editor/index.js
Normal file
31
src/components/editor/index.js
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
import "./styles.css";
|
||||||
|
const embed = require("vega-embed").embed;
|
||||||
|
const get_pdf_from_user_input = require("./main.js").get_pdf_from_user_input;
|
||||||
|
|
||||||
|
let [y, x] = get_pdf_from_user_input("normal(1, 1) / normal(10, 1)");
|
||||||
|
|
||||||
|
let pdf = x.map((val, idx) => ({ x: val, pdf: y[idx] }));
|
||||||
|
|
||||||
|
let spec = {
|
||||||
|
data: {
|
||||||
|
values: pdf
|
||||||
|
},
|
||||||
|
mark: { type: "area", line: true },
|
||||||
|
encoding: {
|
||||||
|
x: { field: "x", type: "quantitative" },
|
||||||
|
y: {
|
||||||
|
field: "pdf",
|
||||||
|
type: "quantitative",
|
||||||
|
scale: { domain: [0, 3 * Math.max(...y)] }
|
||||||
|
}
|
||||||
|
},
|
||||||
|
width: 500
|
||||||
|
};
|
||||||
|
|
||||||
|
embed("#viz", spec);
|
||||||
|
|
||||||
|
console.log(y.reduce((a, b) => a + b));
|
||||||
|
|
||||||
|
document.getElementById("app").innerHTML = `
|
||||||
|
<div id="viz"></div>
|
||||||
|
`;
|
278
src/components/editor/main.js
Normal file
278
src/components/editor/main.js
Normal file
|
@ -0,0 +1,278 @@
|
||||||
|
// The main algorithmic work is done by functions in this module.
|
||||||
|
// It also contains the main function, taking the user's string
|
||||||
|
// and returning pdf values and x's.
|
||||||
|
|
||||||
|
const distrs = require("./distribution.js").distrs;
|
||||||
|
const parse = require("./parse.js");
|
||||||
|
const _math = require("mathjs");
|
||||||
|
const math = _math.create(_math.all);
|
||||||
|
const bst = require("binary-search-tree");
|
||||||
|
|
||||||
|
const NUM_MC_SAMPLES = 300;
|
||||||
|
const OUTPUT_GRID_NUMEL = 300;
|
||||||
|
|
||||||
|
function evenly_spaced_grid(start, stop, numel) {
|
||||||
|
return Array(numel)
|
||||||
|
.fill(0)
|
||||||
|
.map((_, idx) => start + (idx / numel) * (stop - start));
|
||||||
|
}
|
||||||
|
|
||||||
|
function get_distributions(substrings) {
|
||||||
|
// Takes an array of strings like "normal(0, 1)" and
|
||||||
|
// returns the corresponding distribution objects
|
||||||
|
let names_and_args = substrings.map(parse.get_distr_name_and_args);
|
||||||
|
let pdfs = names_and_args.map(x => new distrs[x[0]](x[1]));
|
||||||
|
return pdfs;
|
||||||
|
}
|
||||||
|
|
||||||
|
function update_transformed_divider_points_bst(
|
||||||
|
transform_func,
|
||||||
|
deterministic_pdf,
|
||||||
|
mc_distrs,
|
||||||
|
track_idx,
|
||||||
|
num_mc_samples,
|
||||||
|
bst_pts_and_idxs
|
||||||
|
) {
|
||||||
|
// update the binary search tree with bin points of
|
||||||
|
// deterministic_pdf transformed by tansform func
|
||||||
|
// (transfrom func can be a stocahstic func with parameters
|
||||||
|
// sampled from mc_distrs)
|
||||||
|
var transformed_pts = [];
|
||||||
|
var pdf_inner_idxs = [];
|
||||||
|
var factors = [];
|
||||||
|
var start_pt = Infinity;
|
||||||
|
var end_pt = -Infinity;
|
||||||
|
let use_mc = mc_distrs.length > 0;
|
||||||
|
var num_outer_iters = use_mc ? num_mc_samples : 1;
|
||||||
|
|
||||||
|
for (let sample_idx = 0; sample_idx < num_outer_iters; ++sample_idx) {
|
||||||
|
var this_transformed_pts = deterministic_pdf.divider_pts;
|
||||||
|
if (use_mc) {
|
||||||
|
let samples = mc_distrs.map(x => x.sample());
|
||||||
|
this_transformed_pts = this_transformed_pts.map(x =>
|
||||||
|
transform_func([x].concat(samples))
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
this_transformed_pts = this_transformed_pts.map(x => transform_func([x]));
|
||||||
|
}
|
||||||
|
var this_transformed_pts_paired = [];
|
||||||
|
for (let tp_idx = 0; tp_idx < this_transformed_pts.length - 1; tp_idx++) {
|
||||||
|
let sorted = [
|
||||||
|
this_transformed_pts[tp_idx],
|
||||||
|
this_transformed_pts[tp_idx + 1]
|
||||||
|
].sort((a, b) => a - b);
|
||||||
|
if (sorted[0] < start_pt) {
|
||||||
|
start_pt = sorted[0];
|
||||||
|
}
|
||||||
|
if (sorted[1] > end_pt) {
|
||||||
|
end_pt = sorted[1];
|
||||||
|
}
|
||||||
|
this_transformed_pts_paired.push(sorted);
|
||||||
|
}
|
||||||
|
|
||||||
|
transformed_pts = transformed_pts.concat(this_transformed_pts_paired);
|
||||||
|
|
||||||
|
pdf_inner_idxs = pdf_inner_idxs.concat([
|
||||||
|
...Array(this_transformed_pts_paired.length).keys()
|
||||||
|
]);
|
||||||
|
var this_factors = [];
|
||||||
|
for (let idx = 0; idx < this_transformed_pts_paired.length; idx++) {
|
||||||
|
this_factors.push(
|
||||||
|
(deterministic_pdf.divider_pts[idx + 1] -
|
||||||
|
deterministic_pdf.divider_pts[idx]) /
|
||||||
|
(this_transformed_pts_paired[idx][1] -
|
||||||
|
this_transformed_pts_paired[idx][0])
|
||||||
|
);
|
||||||
|
}
|
||||||
|
factors = factors.concat(this_factors);
|
||||||
|
}
|
||||||
|
for (let i = 0; i < transformed_pts.length; ++i) {
|
||||||
|
bst_pts_and_idxs.insert(transformed_pts[i][0], {
|
||||||
|
start: transformed_pts[i][0],
|
||||||
|
end: transformed_pts[i][1],
|
||||||
|
idx: [track_idx, pdf_inner_idxs[i]],
|
||||||
|
factor: factors[i] / num_outer_iters
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return [start_pt, end_pt];
|
||||||
|
}
|
||||||
|
|
||||||
|
function get_final_pdf(pdf_vals, bst_pts_and_idxs, output_grid) {
|
||||||
|
// Take the binary search tree with transformed bin points,
|
||||||
|
// and an array of pdf values associated with the bins,
|
||||||
|
// and return a pdf over an evenly spaced grid
|
||||||
|
var offset = output_grid[1] / 2 - output_grid[0] / 2;
|
||||||
|
var active_intervals = new Map();
|
||||||
|
var active_endpoints = new bst.AVLTree();
|
||||||
|
var final_pdf_vals = [];
|
||||||
|
for (
|
||||||
|
let out_grid_idx = 0;
|
||||||
|
out_grid_idx < output_grid.length;
|
||||||
|
++out_grid_idx
|
||||||
|
) {
|
||||||
|
let startpoints_within_bin = bst_pts_and_idxs.betweenBounds({
|
||||||
|
$gte: output_grid[out_grid_idx] - offset,
|
||||||
|
$lt: output_grid[out_grid_idx] + offset
|
||||||
|
});
|
||||||
|
for (let interval of startpoints_within_bin) {
|
||||||
|
active_intervals.set(interval.idx, [
|
||||||
|
interval.start,
|
||||||
|
interval.end,
|
||||||
|
interval.factor
|
||||||
|
]);
|
||||||
|
active_endpoints.insert(interval.end, interval.idx);
|
||||||
|
}
|
||||||
|
var contrib = 0;
|
||||||
|
for (let [pdf_idx, bounds_and_ratio] of active_intervals.entries()) {
|
||||||
|
let overlap_start = Math.max(
|
||||||
|
output_grid[out_grid_idx] - offset,
|
||||||
|
bounds_and_ratio[0]
|
||||||
|
);
|
||||||
|
let overlap_end = Math.min(
|
||||||
|
output_grid[out_grid_idx] + offset,
|
||||||
|
bounds_and_ratio[1]
|
||||||
|
);
|
||||||
|
let interval_size = bounds_and_ratio[1] - bounds_and_ratio[0];
|
||||||
|
let contrib_frac =
|
||||||
|
interval_size === 0
|
||||||
|
? 0
|
||||||
|
: (overlap_end - overlap_start) * bounds_and_ratio[2];
|
||||||
|
let t = contrib_frac * pdf_vals[pdf_idx[0]][pdf_idx[1]];
|
||||||
|
contrib += t;
|
||||||
|
}
|
||||||
|
final_pdf_vals.push(contrib);
|
||||||
|
let endpoints_within_bin = active_endpoints.betweenBounds({
|
||||||
|
$gte: output_grid[out_grid_idx] - offset,
|
||||||
|
$lt: output_grid[out_grid_idx] + offset
|
||||||
|
});
|
||||||
|
for (let interval_idx of endpoints_within_bin) {
|
||||||
|
active_intervals.delete(interval_idx);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return final_pdf_vals;
|
||||||
|
}
|
||||||
|
|
||||||
|
function get_pdf_from_user_input(user_input_string) {
|
||||||
|
// Entrypoint. Pass user input strings to this function,
|
||||||
|
// get the corresponding pdf values and input points back.
|
||||||
|
// If the pdf requires monte carlo (it contains a between-distr function)
|
||||||
|
// we first determing which distr to have deterministic
|
||||||
|
// and whih to sample from. This is decided based on which
|
||||||
|
// choice gives the least variance.
|
||||||
|
let parsed = parse.parse_initial_string(user_input_string);
|
||||||
|
let mm_args = parse.separate_mm_args(parsed.mm_args_string);
|
||||||
|
const is_mm = mm_args.distrs.length > 0;
|
||||||
|
let tree = new bst.AVLTree();
|
||||||
|
let possible_start_pts = [];
|
||||||
|
let possible_end_pts = [];
|
||||||
|
let all_vals = [];
|
||||||
|
let weights = is_mm ? math.compile(mm_args.weights).evaluate()._data : [1];
|
||||||
|
let weights_sum = weights.reduce((a, b) => a + b);
|
||||||
|
weights = weights.map(x => x / weights_sum);
|
||||||
|
let n_iters = is_mm ? mm_args.distrs.length : 1;
|
||||||
|
for (let i = 0; i < n_iters; ++i) {
|
||||||
|
let distr_string = is_mm ? mm_args.distrs[i] : parsed.outer_string;
|
||||||
|
var [deterministic_pdf, mc_distrs] = choose_pdf_func(distr_string);
|
||||||
|
var grid_transform = get_grid_transform(distr_string);
|
||||||
|
var [start_pt, end_pt] = update_transformed_divider_points_bst(
|
||||||
|
grid_transform,
|
||||||
|
deterministic_pdf,
|
||||||
|
mc_distrs,
|
||||||
|
i,
|
||||||
|
NUM_MC_SAMPLES,
|
||||||
|
tree
|
||||||
|
);
|
||||||
|
possible_start_pts.push(start_pt);
|
||||||
|
possible_end_pts.push(end_pt);
|
||||||
|
all_vals.push(deterministic_pdf.pdf_vals.map(x => x * weights[i]));
|
||||||
|
}
|
||||||
|
start_pt = Math.min(...possible_start_pts);
|
||||||
|
end_pt = Math.max(...possible_end_pts);
|
||||||
|
let output_grid = evenly_spaced_grid(start_pt, end_pt, OUTPUT_GRID_NUMEL);
|
||||||
|
let final_pdf_vals = get_final_pdf(all_vals, tree, output_grid);
|
||||||
|
return [final_pdf_vals, output_grid];
|
||||||
|
}
|
||||||
|
|
||||||
|
function variance(vals) {
|
||||||
|
var vari = 0;
|
||||||
|
for (let i = 0; i < vals[0].length; ++i) {
|
||||||
|
let mean = 0;
|
||||||
|
let this_vari = 0;
|
||||||
|
for (let val of vals) {
|
||||||
|
mean += val[i] / vals.length;
|
||||||
|
}
|
||||||
|
for (let val of vals) {
|
||||||
|
this_vari += (val[i] - mean) ** 2;
|
||||||
|
}
|
||||||
|
vari += this_vari;
|
||||||
|
}
|
||||||
|
return vari;
|
||||||
|
}
|
||||||
|
|
||||||
|
function pluck_from_array(array, idx) {
|
||||||
|
return [array[idx], array.slice(0, idx).concat(array.slice(idx + 1))];
|
||||||
|
}
|
||||||
|
|
||||||
|
function choose_pdf_func(distr_string) {
|
||||||
|
// If distr_string requires MC, try all possible
|
||||||
|
// choices for the deterministic distribution,
|
||||||
|
// and pick the one with the least variance.
|
||||||
|
var variances = [];
|
||||||
|
let transform_func = get_grid_transform(distr_string);
|
||||||
|
let substrings = parse.get_distr_substrings(distr_string);
|
||||||
|
var pdfs = get_distributions(substrings);
|
||||||
|
if (pdfs.length === 1) {
|
||||||
|
return [pdfs[0], []];
|
||||||
|
}
|
||||||
|
var start_pt = 0;
|
||||||
|
var end_pt = 0;
|
||||||
|
for (let i = 0; i < pdfs.length; ++i) {
|
||||||
|
var outputs = [];
|
||||||
|
for (let j = 0; j < 20; ++j) {
|
||||||
|
let tree = new bst.AVLTree();
|
||||||
|
let [deterministic_pdf, mc_distrs] = pluck_from_array(pdfs, i);
|
||||||
|
let [this_start_pt, this_end_pt] = update_transformed_divider_points_bst(
|
||||||
|
transform_func,
|
||||||
|
deterministic_pdf,
|
||||||
|
mc_distrs,
|
||||||
|
0,
|
||||||
|
10,
|
||||||
|
tree
|
||||||
|
);
|
||||||
|
[start_pt, end_pt] =
|
||||||
|
j === 0 ? [this_start_pt, this_end_pt] : [start_pt, end_pt];
|
||||||
|
var output_grid = evenly_spaced_grid(start_pt, end_pt, 100);
|
||||||
|
let final_pdf_vals = get_final_pdf(
|
||||||
|
[deterministic_pdf.pdf_vals],
|
||||||
|
tree,
|
||||||
|
output_grid
|
||||||
|
);
|
||||||
|
outputs.push(final_pdf_vals);
|
||||||
|
}
|
||||||
|
variances.push(variance(outputs));
|
||||||
|
}
|
||||||
|
let best_variance = Math.min(...variances);
|
||||||
|
let best_idx = variances
|
||||||
|
.map((val, idx) => [val, idx])
|
||||||
|
.filter(x => x[0] === best_variance)[0][1];
|
||||||
|
let mc_distrs = pdfs.slice(0, best_idx).concat(pdfs.slice(best_idx + 1));
|
||||||
|
return [pdfs[best_idx], mc_distrs];
|
||||||
|
}
|
||||||
|
|
||||||
|
function get_grid_transform(distr_string) {
|
||||||
|
let substrings = parse.get_distr_substrings(distr_string);
|
||||||
|
let arg_strings = [];
|
||||||
|
for (let i = 0; i < substrings.length; ++i) {
|
||||||
|
distr_string = distr_string.replace(substrings[i], "x_" + i.toString());
|
||||||
|
arg_strings.push("x_" + i.toString());
|
||||||
|
}
|
||||||
|
let compiled = math.compile(distr_string);
|
||||||
|
function grid_transform(x) {
|
||||||
|
let kv_pairs = arg_strings.map((val, idx) => [val, x[idx]]);
|
||||||
|
let args_obj = Object.fromEntries(new Map(kv_pairs));
|
||||||
|
return compiled.evaluate(args_obj);
|
||||||
|
}
|
||||||
|
return grid_transform;
|
||||||
|
}
|
||||||
|
|
||||||
|
exports.get_pdf_from_user_input = get_pdf_from_user_input;
|
119
src/components/editor/parse.js
Normal file
119
src/components/editor/parse.js
Normal file
|
@ -0,0 +1,119 @@
|
||||||
|
// Functions for parsing/processing user input strings are here
|
||||||
|
const _math = require("mathjs");
|
||||||
|
const math = _math.create(_math.all);
|
||||||
|
|
||||||
|
const DISTR_REGEXS = [
|
||||||
|
/beta\(/g,
|
||||||
|
/(log)?normal\(/g,
|
||||||
|
/multimodal\(/g,
|
||||||
|
/mm\(/g,
|
||||||
|
/uniform\(/g
|
||||||
|
];
|
||||||
|
|
||||||
|
function parse_initial_string(user_input_string) {
|
||||||
|
let outer_output_string = "";
|
||||||
|
let mm_args_string = "";
|
||||||
|
let idx = 0;
|
||||||
|
while (idx < user_input_string.length) {
|
||||||
|
if (
|
||||||
|
user_input_string.substring(idx - 11, idx) === "multimodal(" ||
|
||||||
|
user_input_string.substring(idx - 3, idx) === "mm("
|
||||||
|
) {
|
||||||
|
let num_open_brackets = 1;
|
||||||
|
while (num_open_brackets > 0 && idx < user_input_string.length) {
|
||||||
|
mm_args_string += user_input_string[idx];
|
||||||
|
idx += 1;
|
||||||
|
if (user_input_string[idx] === ")") {
|
||||||
|
num_open_brackets -= 1;
|
||||||
|
} else if (user_input_string[idx] === "(") {
|
||||||
|
num_open_brackets += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
outer_output_string += ")";
|
||||||
|
idx += 1;
|
||||||
|
} else {
|
||||||
|
outer_output_string += user_input_string[idx];
|
||||||
|
idx += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
outer_string: outer_output_string,
|
||||||
|
mm_args_string: mm_args_string
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function separate_mm_args(mm_args_string) {
|
||||||
|
if (mm_args_string.endsWith(",")) {
|
||||||
|
mm_args_string = mm_args_string.slice(0, -1);
|
||||||
|
}
|
||||||
|
let args_array = [];
|
||||||
|
let num_open_brackets = 0;
|
||||||
|
let arg_substring = "";
|
||||||
|
for (let char of mm_args_string) {
|
||||||
|
if (num_open_brackets === 0 && char === ",") {
|
||||||
|
args_array.push(arg_substring.trim());
|
||||||
|
arg_substring = "";
|
||||||
|
} else {
|
||||||
|
if (char === ")" || char === "]") {
|
||||||
|
num_open_brackets -= 1;
|
||||||
|
} else if (char === "(" || char === "[") {
|
||||||
|
num_open_brackets += 1;
|
||||||
|
}
|
||||||
|
arg_substring += char;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
distrs: args_array,
|
||||||
|
weights: arg_substring.trim()
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function get_distr_substrings(distr_string) {
|
||||||
|
let substrings = [];
|
||||||
|
for (let regex of DISTR_REGEXS) {
|
||||||
|
let matches = distr_string.matchAll(regex);
|
||||||
|
for (let match of matches) {
|
||||||
|
let idx = match.index + match[0].length;
|
||||||
|
let num_open_brackets = 1;
|
||||||
|
let distr_substring = "";
|
||||||
|
while (num_open_brackets !== 0 && idx < distr_string.length) {
|
||||||
|
distr_substring += distr_string[idx];
|
||||||
|
if (distr_string[idx] === "(") {
|
||||||
|
num_open_brackets += 1;
|
||||||
|
} else if (distr_string[idx] === ")") {
|
||||||
|
num_open_brackets -= 1;
|
||||||
|
}
|
||||||
|
idx += 1;
|
||||||
|
}
|
||||||
|
substrings.push((match[0] + distr_substring).trim());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return substrings;
|
||||||
|
}
|
||||||
|
|
||||||
|
function get_distr_name_and_args(substr) {
|
||||||
|
let distr_name = "";
|
||||||
|
let args_str = "";
|
||||||
|
let args_flag = false;
|
||||||
|
for (let char of substr) {
|
||||||
|
if (!args_flag && char !== "(") {
|
||||||
|
distr_name += char;
|
||||||
|
}
|
||||||
|
if (args_flag && char !== ")") {
|
||||||
|
args_str += char;
|
||||||
|
}
|
||||||
|
if (char === "(") {
|
||||||
|
args_str += "[";
|
||||||
|
args_flag = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
args_str += "]";
|
||||||
|
let args = math.compile(args_str).evaluate()._data;
|
||||||
|
return [distr_name, args];
|
||||||
|
}
|
||||||
|
|
||||||
|
exports.get_distr_name_and_args = get_distr_name_and_args;
|
||||||
|
exports.get_distr_substrings = get_distr_substrings;
|
||||||
|
exports.separate_mm_args = separate_mm_args;
|
||||||
|
exports.parse_initial_string = parse_initial_string;
|
50
yarn.lock
50
yarn.lock
|
@ -2333,6 +2333,13 @@ binary-extensions@^2.0.0:
|
||||||
resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.0.0.tgz#23c0df14f6a88077f5f986c0d167ec03c3d5537c"
|
resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.0.0.tgz#23c0df14f6a88077f5f986c0d167ec03c3d5537c"
|
||||||
integrity sha512-Phlt0plgpIIBOGTT/ehfFnbNlfsDEiqmzE2KRXoX1bLIlir4X/MR+zSyBEkL05ffWgnRSf/DXv+WrUAVr93/ow==
|
integrity sha512-Phlt0plgpIIBOGTT/ehfFnbNlfsDEiqmzE2KRXoX1bLIlir4X/MR+zSyBEkL05ffWgnRSf/DXv+WrUAVr93/ow==
|
||||||
|
|
||||||
|
binary-search-tree@0.2.6:
|
||||||
|
version "0.2.6"
|
||||||
|
resolved "https://registry.yarnpkg.com/binary-search-tree/-/binary-search-tree-0.2.6.tgz#c6d29194e286827fcffe079010e6bf77def10ce3"
|
||||||
|
integrity sha1-xtKRlOKGgn/P/geQEOa/d97xDOM=
|
||||||
|
dependencies:
|
||||||
|
underscore "~1.4.4"
|
||||||
|
|
||||||
bindings@^1.5.0:
|
bindings@^1.5.0:
|
||||||
version "1.5.0"
|
version "1.5.0"
|
||||||
resolved "https://registry.yarnpkg.com/bindings/-/bindings-1.5.0.tgz#10353c9e945334bc0511a6d90b38fbc7c9c504df"
|
resolved "https://registry.yarnpkg.com/bindings/-/bindings-1.5.0.tgz#10353c9e945334bc0511a6d90b38fbc7c9c504df"
|
||||||
|
@ -2889,7 +2896,7 @@ commander@2, commander@^2.11.0, commander@^2.18.0, commander@^2.19.0, commander@
|
||||||
resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33"
|
resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33"
|
||||||
integrity sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==
|
integrity sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==
|
||||||
|
|
||||||
complex.js@2.0.11:
|
complex.js@2.0.11, complex.js@^2.0.11:
|
||||||
version "2.0.11"
|
version "2.0.11"
|
||||||
resolved "https://registry.yarnpkg.com/complex.js/-/complex.js-2.0.11.tgz#09a873fbf15ffd8c18c9c2201ccef425c32b8bf1"
|
resolved "https://registry.yarnpkg.com/complex.js/-/complex.js-2.0.11.tgz#09a873fbf15ffd8c18c9c2201ccef425c32b8bf1"
|
||||||
integrity sha512-6IArJLApNtdg1P1dFtn3dnyzoZBEF0MwMnrfF1exSBRpZYoy4yieMkpZhQDC0uwctw48vii0CFVyHfpgZ/DfGw==
|
integrity sha512-6IArJLApNtdg1P1dFtn3dnyzoZBEF0MwMnrfF1exSBRpZYoy4yieMkpZhQDC0uwctw48vii0CFVyHfpgZ/DfGw==
|
||||||
|
@ -3632,7 +3639,7 @@ decamelize@^1.2.0:
|
||||||
resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290"
|
resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290"
|
||||||
integrity sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=
|
integrity sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=
|
||||||
|
|
||||||
decimal.js@10.2.0:
|
decimal.js@10.2.0, decimal.js@^10.2.0:
|
||||||
version "10.2.0"
|
version "10.2.0"
|
||||||
resolved "https://registry.yarnpkg.com/decimal.js/-/decimal.js-10.2.0.tgz#39466113a9e036111d02f82489b5fd6b0b5ed231"
|
resolved "https://registry.yarnpkg.com/decimal.js/-/decimal.js-10.2.0.tgz#39466113a9e036111d02f82489b5fd6b0b5ed231"
|
||||||
integrity sha512-vDPw+rDgn3bZe1+F/pyEwb1oMG2XTlRVgAa6B4KccTEpYgF8w6eQllVbQcfIJnZyvzFtFpxnpGtx8dd7DJp/Rw==
|
integrity sha512-vDPw+rDgn3bZe1+F/pyEwb1oMG2XTlRVgAa6B4KccTEpYgF8w6eQllVbQcfIJnZyvzFtFpxnpGtx8dd7DJp/Rw==
|
||||||
|
@ -4043,7 +4050,7 @@ escape-html@~1.0.3:
|
||||||
resolved "https://registry.yarnpkg.com/escape-html/-/escape-html-1.0.3.tgz#0258eae4d3d0c0974de1c169188ef0051d1d1988"
|
resolved "https://registry.yarnpkg.com/escape-html/-/escape-html-1.0.3.tgz#0258eae4d3d0c0974de1c169188ef0051d1d1988"
|
||||||
integrity sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=
|
integrity sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=
|
||||||
|
|
||||||
escape-latex@1.2.0:
|
escape-latex@1.2.0, escape-latex@^1.2.0:
|
||||||
version "1.2.0"
|
version "1.2.0"
|
||||||
resolved "https://registry.yarnpkg.com/escape-latex/-/escape-latex-1.2.0.tgz#07c03818cf7dac250cce517f4fda1b001ef2bca1"
|
resolved "https://registry.yarnpkg.com/escape-latex/-/escape-latex-1.2.0.tgz#07c03818cf7dac250cce517f4fda1b001ef2bca1"
|
||||||
integrity sha512-nV5aVWW1K0wEiUIEdZ4erkGGH8mDxGyxSeqPzRNtWP7ataw+/olFObw7hujFWlVjNsaDFw5VZ5NzVSIqRgfTiw==
|
integrity sha512-nV5aVWW1K0wEiUIEdZ4erkGGH8mDxGyxSeqPzRNtWP7ataw+/olFObw7hujFWlVjNsaDFw5VZ5NzVSIqRgfTiw==
|
||||||
|
@ -4438,7 +4445,7 @@ form-data@~2.3.2:
|
||||||
combined-stream "^1.0.6"
|
combined-stream "^1.0.6"
|
||||||
mime-types "^2.1.12"
|
mime-types "^2.1.12"
|
||||||
|
|
||||||
fraction.js@4.0.12:
|
fraction.js@4.0.12, fraction.js@^4.0.12:
|
||||||
version "4.0.12"
|
version "4.0.12"
|
||||||
resolved "https://registry.yarnpkg.com/fraction.js/-/fraction.js-4.0.12.tgz#0526d47c65a5fb4854df78bc77f7bec708d7b8c3"
|
resolved "https://registry.yarnpkg.com/fraction.js/-/fraction.js-4.0.12.tgz#0526d47c65a5fb4854df78bc77f7bec708d7b8c3"
|
||||||
integrity sha512-8Z1K0VTG4hzYY7kA/1sj4/r1/RWLBD3xwReT/RCrUCbzPszjNQCCsy3ktkU/eaEqX3MYa4pY37a52eiBlPMlhA==
|
integrity sha512-8Z1K0VTG4hzYY7kA/1sj4/r1/RWLBD3xwReT/RCrUCbzPszjNQCCsy3ktkU/eaEqX3MYa4pY37a52eiBlPMlhA==
|
||||||
|
@ -5410,7 +5417,7 @@ iterall@^1.2.1, iterall@^1.2.2:
|
||||||
resolved "https://registry.yarnpkg.com/iterall/-/iterall-1.3.0.tgz#afcb08492e2915cbd8a0884eb93a8c94d0d72fea"
|
resolved "https://registry.yarnpkg.com/iterall/-/iterall-1.3.0.tgz#afcb08492e2915cbd8a0884eb93a8c94d0d72fea"
|
||||||
integrity sha512-QZ9qOMdF+QLHxy1QIpUHUU1D5pS2CG2P69LF6L6CPjPYA/XMOmKV3PZpawHoAjHNyB0swdVTRxdYT4tbBbxqwg==
|
integrity sha512-QZ9qOMdF+QLHxy1QIpUHUU1D5pS2CG2P69LF6L6CPjPYA/XMOmKV3PZpawHoAjHNyB0swdVTRxdYT4tbBbxqwg==
|
||||||
|
|
||||||
javascript-natural-sort@0.7.1:
|
javascript-natural-sort@0.7.1, javascript-natural-sort@^0.7.1:
|
||||||
version "0.7.1"
|
version "0.7.1"
|
||||||
resolved "https://registry.yarnpkg.com/javascript-natural-sort/-/javascript-natural-sort-0.7.1.tgz#f9e2303d4507f6d74355a73664d1440fb5a0ef59"
|
resolved "https://registry.yarnpkg.com/javascript-natural-sort/-/javascript-natural-sort-0.7.1.tgz#f9e2303d4507f6d74355a73664d1440fb5a0ef59"
|
||||||
integrity sha1-+eIwPUUH9tdDVac2ZNFED7Wg71k=
|
integrity sha1-+eIwPUUH9tdDVac2ZNFED7Wg71k=
|
||||||
|
@ -6320,6 +6327,11 @@ jstat@1.9.0:
|
||||||
resolved "https://registry.yarnpkg.com/jstat/-/jstat-1.9.0.tgz#96a625f5697566f6ba3b15832fb371f9451b8614"
|
resolved "https://registry.yarnpkg.com/jstat/-/jstat-1.9.0.tgz#96a625f5697566f6ba3b15832fb371f9451b8614"
|
||||||
integrity sha512-xSsSJ3qY4rS+u8+dAwRcJ0LQGxNdibdW6rSalNPZDbLYkW1C7b0/j79IxXtQjrweqMNI3asN7FCIPceNSIJr2g==
|
integrity sha512-xSsSJ3qY4rS+u8+dAwRcJ0LQGxNdibdW6rSalNPZDbLYkW1C7b0/j79IxXtQjrweqMNI3asN7FCIPceNSIJr2g==
|
||||||
|
|
||||||
|
jstat@1.9.2:
|
||||||
|
version "1.9.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/jstat/-/jstat-1.9.2.tgz#cd2d24df200fd3488861dc7868be01ff65a238cc"
|
||||||
|
integrity sha512-nc3uAadgrWWvJz6RyXUFN0lvTWEXYxMVIrm6ZVoOh4YPLvukLKYpqMofKIE2ReWkL7gFw6hEo6VWZjotYW2Bsw==
|
||||||
|
|
||||||
kind-of@^3.0.2, kind-of@^3.0.3, kind-of@^3.2.0:
|
kind-of@^3.0.2, kind-of@^3.0.3, kind-of@^3.2.0:
|
||||||
version "3.2.2"
|
version "3.2.2"
|
||||||
resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-3.2.2.tgz#31ea21a734bab9bbb0f32466d893aea51e4a3c64"
|
resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-3.2.2.tgz#31ea21a734bab9bbb0f32466d893aea51e4a3c64"
|
||||||
|
@ -6559,6 +6571,20 @@ mathjs@5.10.3:
|
||||||
tiny-emitter "2.1.0"
|
tiny-emitter "2.1.0"
|
||||||
typed-function "1.1.0"
|
typed-function "1.1.0"
|
||||||
|
|
||||||
|
mathjs@6.6.0:
|
||||||
|
version "6.6.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/mathjs/-/mathjs-6.6.0.tgz#0d71c7cc6b50bd112e160b55703a395caf4db4b1"
|
||||||
|
integrity sha512-gYYc1+irFbwuwYUx6O8G2YauvbD1+tPBbq829PaxAiRWpPzPEE8pvwGgvdMuk6c3pqhm6Do/mN26vLiQP46H5A==
|
||||||
|
dependencies:
|
||||||
|
complex.js "^2.0.11"
|
||||||
|
decimal.js "^10.2.0"
|
||||||
|
escape-latex "^1.2.0"
|
||||||
|
fraction.js "^4.0.12"
|
||||||
|
javascript-natural-sort "^0.7.1"
|
||||||
|
seed-random "^2.2.0"
|
||||||
|
tiny-emitter "^2.1.0"
|
||||||
|
typed-function "^1.1.1"
|
||||||
|
|
||||||
md5.js@^1.3.4:
|
md5.js@^1.3.4:
|
||||||
version "1.3.5"
|
version "1.3.5"
|
||||||
resolved "https://registry.yarnpkg.com/md5.js/-/md5.js-1.3.5.tgz#b5d07b8e3216e3e27cd728d72f70d1e6a342005f"
|
resolved "https://registry.yarnpkg.com/md5.js/-/md5.js-1.3.5.tgz#b5d07b8e3216e3e27cd728d72f70d1e6a342005f"
|
||||||
|
@ -9235,7 +9261,7 @@ screenfull@^5.0.0:
|
||||||
resolved "https://registry.yarnpkg.com/screenfull/-/screenfull-5.0.2.tgz#b9acdcf1ec676a948674df5cd0ff66b902b0bed7"
|
resolved "https://registry.yarnpkg.com/screenfull/-/screenfull-5.0.2.tgz#b9acdcf1ec676a948674df5cd0ff66b902b0bed7"
|
||||||
integrity sha512-cCF2b+L/mnEiORLN5xSAz6H3t18i2oHh9BA8+CQlAh5DRw2+NFAGQJOSYbcGw8B2k04g/lVvFcfZ83b3ysH5UQ==
|
integrity sha512-cCF2b+L/mnEiORLN5xSAz6H3t18i2oHh9BA8+CQlAh5DRw2+NFAGQJOSYbcGw8B2k04g/lVvFcfZ83b3ysH5UQ==
|
||||||
|
|
||||||
seed-random@2.2.0:
|
seed-random@2.2.0, seed-random@^2.2.0:
|
||||||
version "2.2.0"
|
version "2.2.0"
|
||||||
resolved "https://registry.yarnpkg.com/seed-random/-/seed-random-2.2.0.tgz#2a9b19e250a817099231a5b99a4daf80b7fbed54"
|
resolved "https://registry.yarnpkg.com/seed-random/-/seed-random-2.2.0.tgz#2a9b19e250a817099231a5b99a4daf80b7fbed54"
|
||||||
integrity sha1-KpsZ4lCoFwmSMaW5mk2vgLf77VQ=
|
integrity sha1-KpsZ4lCoFwmSMaW5mk2vgLf77VQ=
|
||||||
|
@ -9989,7 +10015,7 @@ timsort@^0.3.0:
|
||||||
resolved "https://registry.yarnpkg.com/timsort/-/timsort-0.3.0.tgz#405411a8e7e6339fe64db9a234de11dc31e02bd4"
|
resolved "https://registry.yarnpkg.com/timsort/-/timsort-0.3.0.tgz#405411a8e7e6339fe64db9a234de11dc31e02bd4"
|
||||||
integrity sha1-QFQRqOfmM5/mTbmiNN4R3DHgK9Q=
|
integrity sha1-QFQRqOfmM5/mTbmiNN4R3DHgK9Q=
|
||||||
|
|
||||||
tiny-emitter@2.1.0:
|
tiny-emitter@2.1.0, tiny-emitter@^2.1.0:
|
||||||
version "2.1.0"
|
version "2.1.0"
|
||||||
resolved "https://registry.yarnpkg.com/tiny-emitter/-/tiny-emitter-2.1.0.tgz#1d1a56edfc51c43e863cbb5382a72330e3555423"
|
resolved "https://registry.yarnpkg.com/tiny-emitter/-/tiny-emitter-2.1.0.tgz#1d1a56edfc51c43e863cbb5382a72330e3555423"
|
||||||
integrity sha512-NB6Dk1A9xgQPMoGqC5CVXn123gWyte215ONT5Pp5a0yt4nlEoO1ZWeCwpncaekPHXO60i47ihFnZPiRPjRMq4Q==
|
integrity sha512-NB6Dk1A9xgQPMoGqC5CVXn123gWyte215ONT5Pp5a0yt4nlEoO1ZWeCwpncaekPHXO60i47ihFnZPiRPjRMq4Q==
|
||||||
|
@ -10176,6 +10202,11 @@ typed-function@1.1.0:
|
||||||
resolved "https://registry.yarnpkg.com/typed-function/-/typed-function-1.1.0.tgz#ea149706e0fb42aca1791c053a6d94ccd6c4fdcb"
|
resolved "https://registry.yarnpkg.com/typed-function/-/typed-function-1.1.0.tgz#ea149706e0fb42aca1791c053a6d94ccd6c4fdcb"
|
||||||
integrity sha512-TuQzwiT4DDg19beHam3E66oRXhyqlyfgjHB/5fcvsRXbfmWPJfto9B4a0TBdTrQAPGlGmXh/k7iUI+WsObgORA==
|
integrity sha512-TuQzwiT4DDg19beHam3E66oRXhyqlyfgjHB/5fcvsRXbfmWPJfto9B4a0TBdTrQAPGlGmXh/k7iUI+WsObgORA==
|
||||||
|
|
||||||
|
typed-function@^1.1.1:
|
||||||
|
version "1.1.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/typed-function/-/typed-function-1.1.1.tgz#a1316187ec3628c9e219b91ca96918660a10138e"
|
||||||
|
integrity sha512-RbN7MaTQBZLJYzDENHPA0nUmWT0Ex80KHItprrgbTPufYhIlTePvCXZxyQK7wgn19FW5bnuaBIKcBb5mRWjB1Q==
|
||||||
|
|
||||||
typedarray-to-buffer@^3.1.5:
|
typedarray-to-buffer@^3.1.5:
|
||||||
version "3.1.5"
|
version "3.1.5"
|
||||||
resolved "https://registry.yarnpkg.com/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz#a97ee7a9ff42691b9f783ff1bc5112fe3fca9080"
|
resolved "https://registry.yarnpkg.com/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz#a97ee7a9ff42691b9f783ff1bc5112fe3fca9080"
|
||||||
|
@ -10208,6 +10239,11 @@ uncss@^0.17.2:
|
||||||
postcss-selector-parser "6.0.2"
|
postcss-selector-parser "6.0.2"
|
||||||
request "^2.88.0"
|
request "^2.88.0"
|
||||||
|
|
||||||
|
underscore@~1.4.4:
|
||||||
|
version "1.4.4"
|
||||||
|
resolved "https://registry.yarnpkg.com/underscore/-/underscore-1.4.4.tgz#61a6a32010622afa07963bf325203cf12239d604"
|
||||||
|
integrity sha1-YaajIBBiKvoHljvzJSA88SI51gQ=
|
||||||
|
|
||||||
unicode-canonical-property-names-ecmascript@^1.0.4:
|
unicode-canonical-property-names-ecmascript@^1.0.4:
|
||||||
version "1.0.4"
|
version "1.0.4"
|
||||||
resolved "https://registry.yarnpkg.com/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-1.0.4.tgz#2619800c4c825800efdd8343af7dd9933cbe2818"
|
resolved "https://registry.yarnpkg.com/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-1.0.4.tgz#2619800c4c825800efdd8343af7dd9933cbe2818"
|
||||||
|
|
Loading…
Reference in New Issue
Block a user