tweak: Tools readme
This commit is contained in:
parent
4a2fc6fb89
commit
053c316e73
1702
packages/utility-tools/LICENSE.txt
Normal file
1702
packages/utility-tools/LICENSE.txt
Normal file
File diff suppressed because one or more lines are too long
|
@ -1,9 +1,60 @@
|
||||||
## Utility function processor
|
# Utility Tools
|
||||||
|
|
||||||
This package contains a series of utilities to work with the utility functions produced by [this utility function extractor](https://utility-function-extractor.quantifieduncertainty.org/openphil-2018-ai-risk)
|
This package contains a series of utilities to work with the utility functions produced by [this utility function extractor](https://utility-function-extractor.quantifieduncertainty.org/openphil-2018-ai-risk).
|
||||||
|
|
||||||
### Merge sort
|
## Built with
|
||||||
|
|
||||||
Given a list of elements and a list of utilitity comparisons, sort the list.
|
- [Squiggle](https://www.squiggle-language.com/)
|
||||||
|
- [Nodejs](https://nodejs.org/)
|
||||||
|
- Plain js
|
||||||
|
|
||||||
Gotcha: The list of elements has to be the same list, and in the same order, as that produced when initially doing the comparisons. This is because the merge-sort algorithm depends on the initial order of the list.
|
## Getting started
|
||||||
|
|
||||||
|
### Installation
|
||||||
|
|
||||||
|
```sh
|
||||||
|
yarn add utility-tools
|
||||||
|
```
|
||||||
|
|
||||||
|
then in your file:
|
||||||
|
|
||||||
|
```js
|
||||||
|
import { mergeSort, findPaths, aggregatePaths } from "utility-tools";
|
||||||
|
```
|
||||||
|
|
||||||
|
### Usage
|
||||||
|
|
||||||
|
You can find an example how to use and concatenate these functions in `/src/example.js`, as well as an example of the input format needed in the `input` folder.
|
||||||
|
|
||||||
|
## Interface
|
||||||
|
|
||||||
|
### Merge sort (`mergeSort`)
|
||||||
|
|
||||||
|
Given a list of elements and a list of utilitity comparisons, sort the list. If there are not enough comparisons to implement the merge sort algorithm, return one of the missing comparisons.
|
||||||
|
|
||||||
|
_Gotcha_: The list of elements has to be the same list, and in the same order, as that produced when initially doing the comparisons. This is because the merge-sort algorithm depends on the initial order of the list.
|
||||||
|
|
||||||
|
### Find Paths (`findPaths`)
|
||||||
|
|
||||||
|
Given an (ordered) list of elements and a list of utility comparisons, find all possible monotonous paths from each element to each other. A monotonous path is a path that is either all increasing or all decreasing, relative to the ordering given.
|
||||||
|
|
||||||
|
_Note_: Some elements will have many more paths than others.
|
||||||
|
|
||||||
|
### Aggregate paths (`aggregatePaths`)
|
||||||
|
|
||||||
|
Given a list of path, aggregate them to finally produce an estimate of the relative utility of each element.
|
||||||
|
|
||||||
|
There are two ways of doing this:
|
||||||
|
|
||||||
|
- 1. Aggregate the means (expected values) for each path.
|
||||||
|
- This method is fast
|
||||||
|
- But has the disadvantage the expected value aggregation is tricky, particularly if one of the elements is positive and the other one negative (because then one can't)
|
||||||
|
- 2. Aggregate the distributions given for each path.
|
||||||
|
|
||||||
|
## Roadmap
|
||||||
|
|
||||||
|
I don't have any additions planned for this repository.
|
||||||
|
|
||||||
|
## Contact
|
||||||
|
|
||||||
|
Feel free to shoot me any questions at `nuno.semperelh@protonmail.com`
|
||||||
|
|
|
@ -1,15 +1,24 @@
|
||||||
// EXPORTS
|
// EXPORTS
|
||||||
import { run } from "@quri/squiggle-lang";
|
import { run } from "@quri/squiggle-lang";
|
||||||
|
|
||||||
export function aggregatePaths(pathsArray, nodes) {
|
export async function aggregatePathsThroughMixtureOfDistributions({
|
||||||
pathsArray.map((paths, i) => {
|
pathsArray,
|
||||||
console.log(nodes[i].name);
|
nodes,
|
||||||
|
VERBOSE,
|
||||||
|
}) {
|
||||||
|
let print = (x) => {
|
||||||
|
if (VERBOSE) {
|
||||||
|
console.log(x);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
let result = pathsArray.map((paths, i) => {
|
||||||
|
print(nodes[i].name);
|
||||||
let multipliedDistributions = paths.map(
|
let multipliedDistributions = paths.map(
|
||||||
(path) => path.multipliedDistributionsInPath
|
(path) => path.multipliedDistributionsInPath
|
||||||
);
|
);
|
||||||
console.group();
|
console.group();
|
||||||
console.log("Number of paths: ", multipliedDistributions.length);
|
print("Number of paths: ", multipliedDistributions.length);
|
||||||
// console.log(multipliedDistributions.slice(0, 10));
|
// print(multipliedDistributions.slice(0, 10));
|
||||||
let squiggleCode = `aggregatePath = mx(${multipliedDistributions
|
let squiggleCode = `aggregatePath = mx(${multipliedDistributions
|
||||||
.filter((distributions) => distributions != undefined)
|
.filter((distributions) => distributions != undefined)
|
||||||
// .slice(0, 600)
|
// .slice(0, 600)
|
||||||
|
@ -22,7 +31,7 @@ export function aggregatePaths(pathsArray, nodes) {
|
||||||
let squiggleCodeForMean = squiggleCode + "\n" + "mean(aggregatePath)";
|
let squiggleCodeForMean = squiggleCode + "\n" + "mean(aggregatePath)";
|
||||||
let meanAnswer = run(squiggleCodeForMean);
|
let meanAnswer = run(squiggleCodeForMean);
|
||||||
let mean = meanAnswer.value.value;
|
let mean = meanAnswer.value.value;
|
||||||
console.log(`Mean: ${mean}`);
|
print(`Mean: ${mean}`);
|
||||||
|
|
||||||
// Get the 90% CI
|
// Get the 90% CI
|
||||||
let squiggleCodeFor90CI =
|
let squiggleCodeFor90CI =
|
||||||
|
@ -38,7 +47,7 @@ export function aggregatePaths(pathsArray, nodes) {
|
||||||
let upper = value[1].value;
|
let upper = value[1].value;
|
||||||
return [lower, upper];
|
return [lower, upper];
|
||||||
};
|
};
|
||||||
console.log(
|
print(
|
||||||
`90% confidence interval: ${JSON.stringify(
|
`90% confidence interval: ${JSON.stringify(
|
||||||
processCI90(ci90percentAnswer),
|
processCI90(ci90percentAnswer),
|
||||||
null,
|
null,
|
||||||
|
@ -47,8 +56,98 @@ export function aggregatePaths(pathsArray, nodes) {
|
||||||
);
|
);
|
||||||
// Stop measuring time
|
// Stop measuring time
|
||||||
let end = Date.now();
|
let end = Date.now();
|
||||||
console.log(`${(end - start) / 1000} seconds needed for processing`);
|
print(`${(end - start) / 1000} seconds needed for processing`);
|
||||||
console.groupEnd();
|
console.groupEnd();
|
||||||
console.log("");
|
print("");
|
||||||
|
return {
|
||||||
|
name: nodes[i].name,
|
||||||
|
meanOfAggregatedDistributions: mean,
|
||||||
|
ninetyPercentileConfidenceIntervalOfAggregatedDistributions:
|
||||||
|
ci90percentAnswer,
|
||||||
|
arrayDistributions: squiggleCode,
|
||||||
|
};
|
||||||
|
});
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
const sum = (arr) => arr.reduce((a, b) => a + b, 0);
|
||||||
|
|
||||||
|
export const avg = (arr) => sum(arr) / arr.length;
|
||||||
|
|
||||||
|
export const geomMean = (arr) => {
|
||||||
|
let n = arr.length;
|
||||||
|
let logavg = sum(arr.map((x) => Math.log(x))); // works for low numbers much better
|
||||||
|
// console.log(logavg);
|
||||||
|
let result = Math.exp(logavg / n);
|
||||||
|
return result;
|
||||||
|
};
|
||||||
|
|
||||||
|
export function aggregatePathsThroughMixtureOfMeans({
|
||||||
|
pathsArray,
|
||||||
|
nodes,
|
||||||
|
VERBOSE,
|
||||||
|
}) {
|
||||||
|
let print = (x) => {
|
||||||
|
if (VERBOSE) {
|
||||||
|
console.log(x);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
let result = pathsArray.map((paths, i) => {
|
||||||
|
print(nodes[i].name);
|
||||||
|
let expectedRelativeValues = paths
|
||||||
|
.map((path) => path.expectedRelativeValue)
|
||||||
|
.filter((x) => x != undefined);
|
||||||
|
let hasPositive = expectedRelativeValues.filter((x) => x > 0);
|
||||||
|
let hasNegative = expectedRelativeValues.filter((x) => x < 0);
|
||||||
|
let answer;
|
||||||
|
if (hasPositive.length != 0 && hasNegative.length != 0) {
|
||||||
|
answer = avg(expectedRelativeValues);
|
||||||
|
} else {
|
||||||
|
if (hasNegative.length == 0) {
|
||||||
|
answer = geomMean(expectedRelativeValues);
|
||||||
|
} else {
|
||||||
|
let arrayAsPositive = expectedRelativeValues.map((x) => -x);
|
||||||
|
answer = -geomMean(arrayAsPositive);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
name: nodes[i].name,
|
||||||
|
aggregatedMeans: answer,
|
||||||
|
arrayMeans: expectedRelativeValues,
|
||||||
|
allPositive: hasNegative.length == 0,
|
||||||
|
};
|
||||||
|
});
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function aggregatePaths({
|
||||||
|
pathsArray,
|
||||||
|
nodes,
|
||||||
|
aggregationType,
|
||||||
|
VERBOSE,
|
||||||
|
}) {
|
||||||
|
if (aggregationType == "distribution") {
|
||||||
|
if (VERBOSE == undefined) {
|
||||||
|
VERBOSE = true;
|
||||||
|
}
|
||||||
|
console.log("Warning: this may take a long time");
|
||||||
|
return await aggregatePathsThroughMixtureOfDistributions({
|
||||||
|
pathsArray,
|
||||||
|
nodes,
|
||||||
|
VERBOSE,
|
||||||
|
});
|
||||||
|
} else if (aggregationType == "mean") {
|
||||||
|
return aggregatePathsThroughMixtureOfMeans({
|
||||||
|
pathsArray,
|
||||||
|
nodes,
|
||||||
|
VERBOSE,
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
return aggregatePathsThroughMixtureOfMeans({
|
||||||
|
pathsArray,
|
||||||
|
nodes,
|
||||||
|
VERBOSE,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -24,11 +24,6 @@ async function main() {
|
||||||
const links = JSON.parse(inputLinksAsString);
|
const links = JSON.parse(inputLinksAsString);
|
||||||
const list = JSON.parse(inputListAsString);
|
const list = JSON.parse(inputListAsString);
|
||||||
|
|
||||||
// process file
|
|
||||||
// const sources = links.map((link) => link.source);
|
|
||||||
// const targets = links.map((link) => link.target);
|
|
||||||
// const list = [...new Set([...sources, ...targets])];
|
|
||||||
|
|
||||||
// Merge sort
|
// Merge sort
|
||||||
let mergeSortOutput = mergeSort({ list, links });
|
let mergeSortOutput = mergeSort({ list, links });
|
||||||
// console.log("Output: ");
|
// console.log("Output: ");
|
||||||
|
@ -64,7 +59,12 @@ async function main() {
|
||||||
// console.log(JSON.stringify(paths, null, 4));
|
// console.log(JSON.stringify(paths, null, 4));
|
||||||
|
|
||||||
// Aggregate paths.
|
// Aggregate paths.
|
||||||
let aggregatedPaths = aggregatePaths(paths, nodes);
|
let aggregatedPaths = await aggregatePaths({
|
||||||
|
pathsArray: paths,
|
||||||
|
nodes,
|
||||||
|
aggregationType: "mean", // alternatively: aggregationType: "distribution"
|
||||||
|
VERBOSE: false,
|
||||||
|
});
|
||||||
console.log(aggregatedPaths);
|
console.log(aggregatedPaths);
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -30,7 +30,7 @@ https://github.com/netlify/netlify-plugin-nextjs/#readme
|
||||||
## To do
|
## To do
|
||||||
|
|
||||||
- [x] Extract merge, findPath and aggregatePath functionality into different repos
|
- [x] Extract merge, findPath and aggregatePath functionality into different repos
|
||||||
- [ ] Add functionality like names, etc.
|
- [-] Add functionality like names, etc.
|
||||||
- [x] Send to mongo upon completion
|
- [x] Send to mongo upon completion
|
||||||
- [ ] Add paths table
|
- [ ] Add paths table
|
||||||
- [ ] warn that the paths table is approximate.
|
- [ ] warn that the paths table is approximate.
|
||||||
|
|
|
@ -1,9 +1,11 @@
|
||||||
import React, { useState } from "react";
|
import React, { useState } from "react";
|
||||||
import { mergeSort } from "utility-tools";
|
import { mergeSort } from "utility-tools";
|
||||||
|
|
||||||
|
import { Title } from "./title.js";
|
||||||
import { ProgressIndicator } from "./progressIndicator.js";
|
import { ProgressIndicator } from "./progressIndicator.js";
|
||||||
import { DisplayElementForComparison } from "./displayElementForComparison.js";
|
import { DisplayElementForComparison } from "./displayElementForComparison.js";
|
||||||
import { ComparisonActuator } from "./comparisonActuator.js";
|
import { ComparisonActuator } from "./comparisonActuator.js";
|
||||||
|
|
||||||
import { AdvancedOptions } from "./advancedOptions/advancedOptions.js";
|
import { AdvancedOptions } from "./advancedOptions/advancedOptions.js";
|
||||||
import { Graph } from "./graph/graph.js";
|
import { Graph } from "./graph/graph.js";
|
||||||
import { pushToMongo } from "../lib/pushToMongo.js";
|
import { pushToMongo } from "../lib/pushToMongo.js";
|
||||||
|
@ -110,6 +112,8 @@ export function Homepage({ listOfElementsInit }) {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="block w-full items-center sm:w-full mt-10">
|
<div className="block w-full items-center sm:w-full mt-10">
|
||||||
|
<Title />
|
||||||
|
|
||||||
<ProgressIndicator
|
<ProgressIndicator
|
||||||
numStepsNow={numStepsNow}
|
numStepsNow={numStepsNow}
|
||||||
numElements={listOfElements.length}
|
numElements={listOfElements.length}
|
||||||
|
@ -143,7 +147,6 @@ export function Homepage({ listOfElementsInit }) {
|
||||||
isListOrdered={isListOrdered}
|
isListOrdered={isListOrdered}
|
||||||
mergeSortOrder={mergeSortOrder}
|
mergeSortOrder={mergeSortOrder}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
{/* Advanced options section */}
|
{/* Advanced options section */}
|
||||||
<div>
|
<div>
|
||||||
<AdvancedOptions
|
<AdvancedOptions
|
||||||
|
|
|
@ -1,7 +1,5 @@
|
||||||
import React, { useState } from "react";
|
import React, { useState } from "react";
|
||||||
|
|
||||||
export function Title() {
|
export function Title() {
|
||||||
return (
|
return <h1 className="text-6xl font-bold ">Utility Function Extractor</h1>;
|
||||||
<h1 className="text-6xl font-bold mt-20">Utility Function Extractor</h1>
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,7 +4,6 @@ import "../styles/globals.css";
|
||||||
import "../styles/cytoscape.css";
|
import "../styles/cytoscape.css";
|
||||||
|
|
||||||
import Head from "next/head";
|
import Head from "next/head";
|
||||||
import { Title } from "../components/title.js";
|
|
||||||
|
|
||||||
function MyApp({ Component, pageProps }) {
|
function MyApp({ Component, pageProps }) {
|
||||||
return (
|
return (
|
||||||
|
@ -17,7 +16,6 @@ function MyApp({ Component, pageProps }) {
|
||||||
</Head>
|
</Head>
|
||||||
{/* Content */}
|
{/* Content */}
|
||||||
<main className="inline flex-col items-center w-full flex-1 px-20 text-center">
|
<main className="inline flex-col items-center w-full flex-1 px-20 text-center">
|
||||||
<Title />
|
|
||||||
<Component {...pageProps} />
|
<Component {...pageProps} />
|
||||||
</main>
|
</main>
|
||||||
</div>
|
</div>
|
||||||
|
|
Loading…
Reference in New Issue
Block a user