diff --git a/packages/utility-tools/LICENSE.txt b/packages/utility-tools/LICENSE.txt new file mode 100644 index 0000000..ce361c1 --- /dev/null +++ b/packages/utility-tools/LICENSE.txt @@ -0,0 +1,1702 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Best-README-Template/LICENSE.txt at master · othneildrew/Best-README-Template · GitHub + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ Skip to content + + + + + + + + + + + +
+ +
+ + + + + + + +
+ + + +
+ + + + + + + + + +
+
+
+ + + + + + + + + + + + + + +
+ + + + + + +
+ + +
+ + + + + + + + +Permalink + +
+ +
+
+ + + master + + + + +
+
+
+ Switch branches/tags + +
+ + + +
+ +
+ +
+ + +
+ +
+ + + + + + + + + + + + + + + +
+ + +
+
+
+
+ +
+ +
+ + + Go to file + + +
+ + + + + +
+
+
+ + + +
+
+
+ +

+ othneildrew/Best-README-Template + is licensed under the +

+

MIT License

+

A short and simple permissive license with conditions only requiring preservation of copyright and license notices. Licensed works, modifications, and larger works may be distributed under different terms and without source code.

+
+ +
+
+

Permissions

+
    +
  • + + + Commercial use + +
  • +
  • + + + Modification + +
  • +
  • + + + Distribution + +
  • +
  • + + + Private use + +
  • +
+
+
+

Limitations

+
    +
  • + + + Liability + +
  • +
  • + + + Warranty + +
  • +
+
+
+

Conditions

+
    +
  • + + + License and copyright notice + +
  • +
+
+
+
+

+ This is not legal advice. + Learn more about repository licenses. +

+
+ + + + + + + +
+ +
+
+ + + + +
+ + Latest commit + d9406e6 + Oct 2, 2021 + + + + + + History + + +
+
+
…o top link
+ +
+ +
+
+ + + 1 + + contributor + + +
+ +

+ Users who have contributed to this file +

+
+ + + + + + +
+
+
+
+ + + + + + + + +
+ +
+ + +
+ + 21 lines (17 sloc) + + 1.04 KB +
+ +
+ + + + +
+ + + +
+
+
+
+ +
+
+
+
+
+ + + Open in GitHub Desktop +
+
+
+
+
+ + + +
+
+ + + +
+
+ +
+ +
+
+ + + +
+ + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MIT License
+
Copyright (c) 2021 Othneil Drew
+
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
+
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
+
+ + + +
+ +
+ + + + +
+ + +
+ + +
+
+ + +
+ +
+ + +
+ + +
+
+ +
+ + + + + + + + + + + + + + + + + + + + + diff --git a/packages/utility-tools/README.md b/packages/utility-tools/README.md index 0ee865f..90a0101 100644 --- a/packages/utility-tools/README.md +++ b/packages/utility-tools/README.md @@ -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` diff --git a/packages/utility-tools/src/aggregatePaths.js b/packages/utility-tools/src/aggregatePaths.js index 0a61e7f..b880e8b 100644 --- a/packages/utility-tools/src/aggregatePaths.js +++ b/packages/utility-tools/src/aggregatePaths.js @@ -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, + }); + } } diff --git a/packages/utility-tools/src/process-input.js b/packages/utility-tools/src/example.js similarity index 89% rename from packages/utility-tools/src/process-input.js rename to packages/utility-tools/src/example.js index 1dc06fd..c5cc202 100644 --- a/packages/utility-tools/src/process-input.js +++ b/packages/utility-tools/src/example.js @@ -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); } } diff --git a/packages/webpage-refactor/README.md b/packages/webpage-refactor/README.md index 1b55fc9..77c427a 100644 --- a/packages/webpage-refactor/README.md +++ b/packages/webpage-refactor/README.md @@ -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. diff --git a/packages/webpage-refactor/components/homepage.js b/packages/webpage-refactor/components/homepage.js index 9455f3d..c1aa0b5 100644 --- a/packages/webpage-refactor/components/homepage.js +++ b/packages/webpage-refactor/components/homepage.js @@ -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 (
+ + <ProgressIndicator numStepsNow={numStepsNow} numElements={listOfElements.length} @@ -143,7 +147,6 @@ export function Homepage({ listOfElementsInit }) { isListOrdered={isListOrdered} mergeSortOrder={mergeSortOrder} /> - {/* Advanced options section */} <div> <AdvancedOptions diff --git a/packages/webpage-refactor/components/title.js b/packages/webpage-refactor/components/title.js index 2656a42..57f4126 100644 --- a/packages/webpage-refactor/components/title.js +++ b/packages/webpage-refactor/components/title.js @@ -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>; } diff --git a/packages/webpage-refactor/pages/_app.js b/packages/webpage-refactor/pages/_app.js index bd1ab3e..b91f2d4 100644 --- a/packages/webpage-refactor/pages/_app.js +++ b/packages/webpage-refactor/pages/_app.js @@ -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>