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
|
||||
import { run } from "@quri/squiggle-lang";
|
||||
|
||||
export function aggregatePaths(pathsArray, nodes) {
|
||||
pathsArray.map((paths, i) => {
|
||||
console.log(nodes[i].name);
|
||||
export async function aggregatePathsThroughMixtureOfDistributions({
|
||||
pathsArray,
|
||||
nodes,
|
||||
VERBOSE,
|
||||
}) {
|
||||
let print = (x) => {
|
||||
if (VERBOSE) {
|
||||
console.log(x);
|
||||
}
|
||||
};
|
||||
let result = pathsArray.map((paths, i) => {
|
||||
print(nodes[i].name);
|
||||
let multipliedDistributions = paths.map(
|
||||
(path) => path.multipliedDistributionsInPath
|
||||
);
|
||||
console.group();
|
||||
console.log("Number of paths: ", multipliedDistributions.length);
|
||||
// console.log(multipliedDistributions.slice(0, 10));
|
||||
print("Number of paths: ", multipliedDistributions.length);
|
||||
// print(multipliedDistributions.slice(0, 10));
|
||||
let squiggleCode = `aggregatePath = mx(${multipliedDistributions
|
||||
.filter((distributions) => distributions != undefined)
|
||||
// .slice(0, 600)
|
||||
|
@ -22,7 +31,7 @@ export function aggregatePaths(pathsArray, nodes) {
|
|||
let squiggleCodeForMean = squiggleCode + "\n" + "mean(aggregatePath)";
|
||||
let meanAnswer = run(squiggleCodeForMean);
|
||||
let mean = meanAnswer.value.value;
|
||||
console.log(`Mean: ${mean}`);
|
||||
print(`Mean: ${mean}`);
|
||||
|
||||
// Get the 90% CI
|
||||
let squiggleCodeFor90CI =
|
||||
|
@ -38,7 +47,7 @@ export function aggregatePaths(pathsArray, nodes) {
|
|||
let upper = value[1].value;
|
||||
return [lower, upper];
|
||||
};
|
||||
console.log(
|
||||
print(
|
||||
`90% confidence interval: ${JSON.stringify(
|
||||
processCI90(ci90percentAnswer),
|
||||
null,
|
||||
|
@ -47,8 +56,98 @@ export function aggregatePaths(pathsArray, nodes) {
|
|||
);
|
||||
// Stop measuring time
|
||||
let end = Date.now();
|
||||
console.log(`${(end - start) / 1000} seconds needed for processing`);
|
||||
print(`${(end - start) / 1000} seconds needed for processing`);
|
||||
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 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
|
||||
let mergeSortOutput = mergeSort({ list, links });
|
||||
// console.log("Output: ");
|
||||
|
@ -64,7 +59,12 @@ async function main() {
|
|||
// console.log(JSON.stringify(paths, null, 4));
|
||||
|
||||
// Aggregate paths.
|
||||
let aggregatedPaths = aggregatePaths(paths, nodes);
|
||||
let aggregatedPaths = await aggregatePaths({
|
||||
pathsArray: paths,
|
||||
nodes,
|
||||
aggregationType: "mean", // alternatively: aggregationType: "distribution"
|
||||
VERBOSE: false,
|
||||
});
|
||||
console.log(aggregatedPaths);
|
||||
}
|
||||
}
|
|
@ -30,7 +30,7 @@ https://github.com/netlify/netlify-plugin-nextjs/#readme
|
|||
## To do
|
||||
|
||||
- [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
|
||||
- [ ] Add paths table
|
||||
- [ ] warn that the paths table is approximate.
|
||||
|
|
|
@ -1,9 +1,11 @@
|
|||
import React, { useState } from "react";
|
||||
import { mergeSort } from "utility-tools";
|
||||
|
||||
import { Title } from "./title.js";
|
||||
import { ProgressIndicator } from "./progressIndicator.js";
|
||||
import { DisplayElementForComparison } from "./displayElementForComparison.js";
|
||||
import { ComparisonActuator } from "./comparisonActuator.js";
|
||||
|
||||
import { AdvancedOptions } from "./advancedOptions/advancedOptions.js";
|
||||
import { Graph } from "./graph/graph.js";
|
||||
import { pushToMongo } from "../lib/pushToMongo.js";
|
||||
|
@ -110,6 +112,8 @@ export function Homepage({ listOfElementsInit }) {
|
|||
|
||||
return (
|
||||
<div className="block w-full items-center sm:w-full mt-10">
|
||||
<Title />
|
||||
|
||||
<ProgressIndicator
|
||||
numStepsNow={numStepsNow}
|
||||
numElements={listOfElements.length}
|
||||
|
@ -143,7 +147,6 @@ export function Homepage({ listOfElementsInit }) {
|
|||
isListOrdered={isListOrdered}
|
||||
mergeSortOrder={mergeSortOrder}
|
||||
/>
|
||||
|
||||
{/* Advanced options section */}
|
||||
<div>
|
||||
<AdvancedOptions
|
||||
|
|
|
@ -1,7 +1,5 @@
|
|||
import React, { useState } from "react";
|
||||
|
||||
export function Title() {
|
||||
return (
|
||||
<h1 className="text-6xl font-bold mt-20">Utility Function Extractor</h1>
|
||||
);
|
||||
return <h1 className="text-6xl font-bold ">Utility Function Extractor</h1>;
|
||||
}
|
||||
|
|
|
@ -4,7 +4,6 @@ import "../styles/globals.css";
|
|||
import "../styles/cytoscape.css";
|
||||
|
||||
import Head from "next/head";
|
||||
import { Title } from "../components/title.js";
|
||||
|
||||
function MyApp({ Component, pageProps }) {
|
||||
return (
|
||||
|
@ -17,7 +16,6 @@ function MyApp({ Component, pageProps }) {
|
|||
</Head>
|
||||
{/* Content */}
|
||||
<main className="inline flex-col items-center w-full flex-1 px-20 text-center">
|
||||
<Title />
|
||||
<Component {...pageProps} />
|
||||
</main>
|
||||
</div>
|
||||
|
|
Loading…
Reference in New Issue
Block a user