feat: Get prototype working.
Display still missing, but some core functionality already works.
1
.gitignore
vendored
|
@ -18,6 +18,7 @@ packages/webpage/pages/.old
|
|||
|
||||
# dependencies
|
||||
**/node_modules
|
||||
node_modules/
|
||||
/.pnp
|
||||
.pnp.js
|
||||
|
||||
|
|
114
README.md
|
@ -1,8 +1,114 @@
|
|||
## About
|
||||
|
||||
This repository creates a react webpage that allows to extract a utility function from possibly inconsistent binary comparisons.
|
||||
|
||||
It presents the users with a series of elements to compare, using merge-sort in the background to cleverly minimize the number of choices needed.
|
||||
|
||||
<p align="center">
|
||||
<img width="50%" height="50%" src="./packages/webpage-refactor/public/example-graph.png">
|
||||
<img width="50%" height="50%" src="./public/example-prompt.png">
|
||||
</p>
|
||||
|
||||
This repository contains the code for the website [utility-function-extractor.quantifieduncertainty.org/](https://utility-function-extractor.quantifieduncertainty.org/) and tools to analyze utility comparisons. For details, see the relevant folders.
|
||||
Then, it cleverly aggregates them, on the one hand by producing a graphical representation:
|
||||
|
||||
- [Webpage repository](https://github.com/quantified-uncertainty/utility-function-extractor/tree/master/packages/webpage-refactor)
|
||||
- [Tools repository](https://github.com/quantified-uncertainty/utility-function-extractor/tree/master/packages/utility-tools)
|
||||
<p align="center">
|
||||
<img width="50%" height="50%" src="./public/example-graph.png">
|
||||
</p>
|
||||
|
||||
and on the other hand doing some fast and clever mean aggregation [^1]:
|
||||
|
||||
<p align="center">
|
||||
<img width="50%" height="50%" src="./public/example-table.png">
|
||||
</p>
|
||||
|
||||
Initially, users could only input numbers, e.g., "A is `3` times better than B". But now, users can also input distributions, using the [squiggle](https://www.squiggle-language.com/) syntax, e.g., "A is `1 to 10` times better than B", or "A is `mm(normal(1, 10), uniform(0,100))` better than B".
|
||||
|
||||
**If you want to use the utility function extractor for a project, we are happy to add a page for your project, like `utility-function-extractor.quantifieduncertainty.org/your-project`**.
|
||||
|
||||
## Built with
|
||||
|
||||
- [Nextjs](https://nextjs.org/)
|
||||
- [Netlify](https://github.com/netlify/netlify-plugin-nextjs/#readme)
|
||||
- [React](https://reactjs.org/)
|
||||
- [Squiggle](https://www.squiggle-language.com/)
|
||||
- [Utility tools](https://github.com/quantified-uncertainty/utility-function-extractor/tree/master/packages/utility-tools)
|
||||
|
||||
## Usage
|
||||
|
||||
Navigate to [utility-function-extractor.quantifieduncertainty.org/](https://utility-function-extractor.quantifieduncertainty.org/), and start comparing objects.
|
||||
|
||||
You can change the list of objects to be compared by clicking on "advanced options".
|
||||
|
||||
After comparing objects for a while, you will get a table and a graph with results. You can also use the [utility tools](https://github.com/quantified-uncertainty/utility-function-extractor/tree/master/packages/utility-tools) package to process these results, for which you will need the json of comparisons, which can be found in "Advanced options" -> "Load comparisons"
|
||||
|
||||
## Notes
|
||||
|
||||
The core structure is json array of objects. Only the "name" attribute is required. If there is a "url", it is displayed nicely.
|
||||
|
||||
```
|
||||
[
|
||||
{
|
||||
"name": "Peter Parker",
|
||||
"someOptionalKey": "...",
|
||||
"anotherMoreOptionalKey": "...",
|
||||
},
|
||||
{
|
||||
"name": "Spiderman",
|
||||
"someOptionalKey": "...",
|
||||
"anotherMoreOptionalKey": "..."
|
||||
}
|
||||
]
|
||||
```
|
||||
|
||||
The core structure for links is as follows:
|
||||
|
||||
```
|
||||
[
|
||||
{
|
||||
"source": "Peter Parker",
|
||||
"target": "Spiderman",
|
||||
"squiggleString": "1 to 100",
|
||||
"distance": 26.639800977355474
|
||||
},
|
||||
{
|
||||
"source": "Spiderman",
|
||||
"target": "Jonah Jameson",
|
||||
"squiggleString": "20 to 2000",
|
||||
"distance": 6.76997149080232
|
||||
},
|
||||
|
||||
]
|
||||
```
|
||||
|
||||
A previous version of this webpage had a more complicated structure, but it has since been simplified.
|
||||
|
||||
## Contributions and help
|
||||
|
||||
We welcome PR requests.
|
||||
|
||||
## License
|
||||
|
||||
Distributed under the MIT License. See LICENSE.txt for more information.
|
||||
|
||||
## To do
|
||||
|
||||
- [x] Extract merge, findPath and aggregatePath functionality into different repos
|
||||
- [x] Send to mongo upon completion
|
||||
- [x] Push to github
|
||||
- [x] Push to netlify
|
||||
- [x] Don't allow further comparisons after completion
|
||||
- [x] Paths table
|
||||
- [x] Add paths table
|
||||
- [x] warn that the paths table is approximate.
|
||||
- I really don't feel like re-adding this after having worked out the distribution rather than the mean aggregation
|
||||
- On the other hand, I think it does make it more user to other users.
|
||||
- [x] Change README.
|
||||
- [ ] Add functionality like names, etc.
|
||||
- I also don't feel like doing this
|
||||
- [ ] Look back at Amazon thing which has been running
|
||||
- [ ] Simplify Graph and DynamicSquiggleChart components
|
||||
- [ ] Add squiggle component to initial comparison?
|
||||
- [ ] Understand why the rewrite doesn't
|
||||
- Maybe: When two elements are judged to be roughly equal
|
||||
- Maybe: Slightly different merge-sort algorithm.
|
||||
|
||||
[^1]: The program takes each element as a reference point in turn, and computing the possible distances from that reference point to all other points, and taking the geometric mean of these distances. This produces a number representing the value of each element, such that the ratios between elements represent the user's preferences: a utility function. However, this isn't perfect; the principled approach woud be to aggregate the distributions rather than their means. But this principled approach is much more slowly. For the principled approach, see the `utility-tools` repository.
|
||||
|
|
|
@ -23,28 +23,29 @@ const SquiggleChart = dynamic(
|
|||
const effectButtonStyle =
|
||||
"bg-transparent m-2 hover:bg-blue-500 text-blue-700 font-semibold hover:text-white py-2 px-4 border border-blue-500 hover:border-transparent rounded mt-5";
|
||||
|
||||
export function DynamicSquiggleChart({ link, stopShowing }) {
|
||||
if (link == null) {
|
||||
export function DynamicSquiggleChart({ element, stopShowing }) {
|
||||
if (element == null) {
|
||||
return "";
|
||||
} else {
|
||||
let usefulLink = {
|
||||
source: link.source,
|
||||
target: link.target,
|
||||
squiggleString: link.squiggleString,
|
||||
let usefulElement = {
|
||||
name: element.id,
|
||||
squiggleString: element.fn,
|
||||
formula: element.formula
|
||||
};
|
||||
return (
|
||||
<div className="">
|
||||
<h3 className="text-2xl font-bold mb-5">{usefulElement.name}</h3>
|
||||
<textarea
|
||||
value={JSON.stringify(usefulLink, null, 4)}
|
||||
value={JSON.stringify(usefulElement, null, 4)}
|
||||
//onChange={handleChange}
|
||||
disabled={true}
|
||||
rows={JSON.stringify(usefulLink, null, 4).split("\n").length}
|
||||
rows={JSON.stringify(usefulElement, null, 4).split("\n").length}
|
||||
cols={37}
|
||||
className="text-left text-gray-600 bg-white rounded text-normal p-6 border-0 shadow outline-none focus:outline-none focus:ring mb-4"
|
||||
/>
|
||||
<SquiggleChart
|
||||
squiggleString={link.squiggleString}
|
||||
width={445}
|
||||
squiggleString={element.squiggleString}
|
||||
width={500}
|
||||
height={200}
|
||||
showSummary={true}
|
||||
showTypes={true}
|
75
components/dynamicSquiggleChartPartial.js
Normal file
|
@ -0,0 +1,75 @@
|
|||
import React from "react";
|
||||
// import { SquiggleChart } from "@quri/squiggle-components";
|
||||
|
||||
import dynamic from "next/dynamic";
|
||||
|
||||
const SquiggleChart = dynamic(
|
||||
() => import("@quri/squiggle-components").then((mod) => mod.SquiggleChart),
|
||||
{
|
||||
loading: () => <p>Loading...</p>,
|
||||
ssr: false,
|
||||
}
|
||||
);
|
||||
/*
|
||||
const SquiggleChart = dynamic(
|
||||
() => import("@quri/squiggle-components").then((mod) => mod.SquiggleChart),
|
||||
{
|
||||
suspense: true,
|
||||
ssr: false,
|
||||
}
|
||||
);
|
||||
*/
|
||||
|
||||
const effectButtonStyle =
|
||||
"bg-transparent m-2 hover:bg-blue-500 text-blue-700 font-semibold hover:text-white py-2 px-4 border border-blue-500 hover:border-transparent rounded mt-5";
|
||||
|
||||
export function DynamicSquiggleChart({ element, stopShowing }) {
|
||||
if (element == null) {
|
||||
return "";
|
||||
} else {
|
||||
let usefulElement = {
|
||||
name: element.id,
|
||||
squiggleString: element.fn,
|
||||
formula: element.formula
|
||||
};
|
||||
return (
|
||||
<div className="">
|
||||
<h3 className="text-2xl font-bold mb-5">{usefulElement.name}</h3>
|
||||
<textarea
|
||||
value={JSON.stringify(usefulElement, null, 4)}
|
||||
//onChange={handleChange}
|
||||
disabled={true}
|
||||
rows={JSON.stringify(usefulElement, null, 4).split("\n").length}
|
||||
cols={37}
|
||||
className="text-left text-gray-600 bg-white rounded text-normal p-6 border-0 shadow outline-none focus:outline-none focus:ring mb-4"
|
||||
/>
|
||||
<SquiggleChart
|
||||
squiggleString={element.squiggleString}
|
||||
width={500}
|
||||
height={200}
|
||||
showSummary={true}
|
||||
showTypes={true}
|
||||
/>
|
||||
{/*
|
||||
SquiggleChart props:
|
||||
squiggleString?: string;
|
||||
sampleCount?: number;
|
||||
environment?: environment;
|
||||
chartSettings?: FunctionChartSettings;
|
||||
onChange?(expr: squiggleExpression): void;
|
||||
width?: number;
|
||||
height?: number;
|
||||
bindings?: bindings;
|
||||
jsImports?: jsImports;
|
||||
showSummary?: boolean;
|
||||
showTypes?: boolean;
|
||||
showControls?: boolean;
|
||||
*/}
|
||||
|
||||
<button className={effectButtonStyle} onClick={() => stopShowing()}>
|
||||
Hide chart
|
||||
</button>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
257
components/graph/createGraph.js
Normal file
|
@ -0,0 +1,257 @@
|
|||
import { run, runPartial, mergeBindings } from "@quri/squiggle-lang";
|
||||
|
||||
|
||||
function miniReducer(obj, parentName) {
|
||||
let nodes = []
|
||||
let edges = []
|
||||
let bindings = [];
|
||||
|
||||
let inputs = obj.inputs
|
||||
let fn = obj.fn
|
||||
|
||||
for (let childName of Object.keys(inputs)) {
|
||||
if (typeof inputs[childName] == "string") {
|
||||
// Produce bindings
|
||||
let childBindingSquiggleStrings = `${childName} = ${inputs[childName]}`;
|
||||
let childBinding = runPartial(childBindingSquiggleStrings).value;
|
||||
bindings.push(childBinding);
|
||||
|
||||
// Produce value
|
||||
let childValueSquiggleString = `${childBindingSquiggleStrings}
|
||||
${childName}`
|
||||
let childResultValue = run(childValueSquiggleString)
|
||||
|
||||
// Process value for node and edges
|
||||
if (childResultValue.tag == "Error") {
|
||||
return childResultValue
|
||||
} else {
|
||||
// Node
|
||||
let childNode = ({
|
||||
tag: 'Ok',
|
||||
id: childName,
|
||||
value: childResultValue.value,
|
||||
fn: inputs[childName]
|
||||
})
|
||||
nodes.push(childNode)
|
||||
|
||||
// Edge
|
||||
let edge = ({
|
||||
id: `${childName}->${parentName}`, // has to be unique
|
||||
source: `${childName}`,
|
||||
target: `${parentName}`,
|
||||
})
|
||||
edges.push(edge)
|
||||
}
|
||||
} else {
|
||||
// Produce data
|
||||
let childNodeOutput = miniReducer(inputs[childName], childName);
|
||||
if (childNodeOutput.tag == "Error") {
|
||||
return childNodeOutput
|
||||
} else {
|
||||
// Bindings
|
||||
bindings.push(childNodeOutput.binding)
|
||||
// Nodes from child node
|
||||
nodes.push(...childNodeOutput.nodes)
|
||||
// Edges from child node
|
||||
edges.push(...childNodeOutput.edges)
|
||||
|
||||
/* Child node is included in the childNodeOutput.nodes
|
||||
let childNode = {
|
||||
tag: 'Ok',
|
||||
id: input,
|
||||
value: childNodeOutput.value,
|
||||
fn: inputs[childName].fn
|
||||
};
|
||||
nodes.push(childNode)
|
||||
*/
|
||||
// Child edge
|
||||
let edge = ({
|
||||
id: `${childName}->${parentName}`, // has to be unique
|
||||
source: `${childName}`,
|
||||
target: `${parentName}`,
|
||||
})
|
||||
edges.push(edge)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let parentBindingSquiggleString = `${parentName} = {
|
||||
${fn}
|
||||
}`;
|
||||
let parentResultSquiggleString = `${parentName} = {
|
||||
${fn}
|
||||
}
|
||||
${parentName}`;
|
||||
let parentBinding = runPartial(
|
||||
parentBindingSquiggleString,
|
||||
mergeBindings(bindings)
|
||||
).value;
|
||||
|
||||
if (parentBinding.tag == "Error") {
|
||||
return parentBinding
|
||||
}
|
||||
|
||||
let parentValue = run(parentResultSquiggleString, mergeBindings(bindings));
|
||||
if (parentValue.tag == "Error") {
|
||||
// console.log(bindings)
|
||||
return parentValue
|
||||
}
|
||||
|
||||
let resultNode = ({
|
||||
tag: 'Ok',
|
||||
id: parentName,
|
||||
value: parentValue.value,
|
||||
fn: fn
|
||||
})
|
||||
|
||||
nodes.push(resultNode)
|
||||
// console.log("resultNode", resultNode)
|
||||
let result = {
|
||||
...resultNode,
|
||||
value: parentValue,
|
||||
binding: parentBinding,
|
||||
nodes: nodes,
|
||||
edges: edges
|
||||
};
|
||||
return (result);
|
||||
}
|
||||
|
||||
export function createGraph() {
|
||||
|
||||
let utility = {
|
||||
inputs: {
|
||||
productivity: {
|
||||
inputs: {
|
||||
hours: `4 to 12`,
|
||||
efficiency: `0.1 to 10`,
|
||||
},
|
||||
fn: `
|
||||
hours * efficiency
|
||||
`,
|
||||
},
|
||||
},
|
||||
fn: `
|
||||
x = 1 to 10
|
||||
r = productivity * (1 to 10) * x
|
||||
mean(r)`,
|
||||
};
|
||||
|
||||
let reducerResult = miniReducer(utility, "utility");
|
||||
|
||||
if (reducerResult.tag == "Error") {
|
||||
return reducerResult
|
||||
} else {
|
||||
// console.log("reducerResult", reducerResult)
|
||||
let {nodes, edges} = reducerResult
|
||||
let nodeElements = nodes.map(node => ({ data: { ...node, name: node.id} }))
|
||||
let edgeElements = edges.map(edge => ({ data: { ...edge, name: edge.id } }))
|
||||
let answer = { nodeElements, edgeElements }
|
||||
return answer
|
||||
}
|
||||
|
||||
// return { nodeElements: [], edgeElements: [] }
|
||||
/*
|
||||
|
||||
*/
|
||||
// return (resultUtility)
|
||||
|
||||
// Then the rest should be doable without all that much work.
|
||||
// Some duplication of efforts, but I don't really care:
|
||||
}
|
||||
|
||||
export function createGraph0() {
|
||||
let nodeElements = [
|
||||
{
|
||||
data: {
|
||||
id: "Total utility",
|
||||
squiggleString: "1 to 1000",
|
||||
formula: "now + soon + later"
|
||||
}
|
||||
},
|
||||
{
|
||||
data: {
|
||||
id: "now",
|
||||
squiggleString: "1 to 2",
|
||||
formula: "subjective estimation"
|
||||
},
|
||||
},
|
||||
{
|
||||
data: {
|
||||
id: "soon",
|
||||
squiggleString: "10 to 200",
|
||||
formula: "subjective estimation"
|
||||
},
|
||||
},
|
||||
{
|
||||
data: {
|
||||
id: "later",
|
||||
squiggleString: "1 to 500",
|
||||
formula: "subjective estimation"
|
||||
},
|
||||
},
|
||||
{
|
||||
data: {
|
||||
id: "discount rate",
|
||||
squiggleString: "0.001 to 0.03",
|
||||
formula: "subjective estimation"
|
||||
},
|
||||
},
|
||||
{
|
||||
data: {
|
||||
id: "return rate",
|
||||
squiggleString: "1 to 2"
|
||||
}
|
||||
},
|
||||
]
|
||||
let edgeElements = [
|
||||
{
|
||||
data: {
|
||||
id: "link-1",
|
||||
source: "now",
|
||||
target: "Total utility",
|
||||
},
|
||||
},
|
||||
{
|
||||
data: {
|
||||
id: "link-2",
|
||||
source: "soon",
|
||||
target: "Total utility",
|
||||
},
|
||||
},
|
||||
{
|
||||
data: {
|
||||
id: "link-3",
|
||||
source: "later",
|
||||
target: "Total utility",
|
||||
},
|
||||
},
|
||||
{
|
||||
data: {
|
||||
id: "link-4",
|
||||
source: "discount rate",
|
||||
target: "later",
|
||||
},
|
||||
},
|
||||
{
|
||||
data: {
|
||||
id: "link-5",
|
||||
source: "return rate",
|
||||
target: "later",
|
||||
}
|
||||
},
|
||||
]
|
||||
|
||||
//
|
||||
|
||||
let squiggleInJs = ({
|
||||
|
||||
displayName: "Total utility",
|
||||
varName: "utility",
|
||||
inputs: {
|
||||
|
||||
},
|
||||
fn: ``
|
||||
})
|
||||
//
|
||||
return { nodeElements, edgeElements }
|
||||
}
|
203
components/graph/graph.js
Normal file
|
@ -0,0 +1,203 @@
|
|||
import React, { useRef, useState, useEffect } from "react";
|
||||
import cytoscape from "cytoscape";
|
||||
import dagre from 'cytoscape-dagre';
|
||||
import { DynamicSquiggleChart } from "../dynamicSquiggleChart.js";
|
||||
import { createGraph } from "./createGraph"
|
||||
|
||||
export function Graph({ }) {
|
||||
const containerRef = useRef("hello-world");
|
||||
const [cs, setCs] = useState(null); /// useState("invisible");
|
||||
const [selectedElement, setSelectedElement] = useState(null);
|
||||
const [selectedElementTimeout, setSelectedElementTimeout] = useState(null);
|
||||
//let { nodeElements, edgeElements } = createGraph()
|
||||
const graphInit = createGraph()
|
||||
const [nodeElements, setNodeElements] = useState(graphInit.nodeElements)
|
||||
const [edgeElements, setEdgeElements] = useState(graphInit.edgeElements)
|
||||
|
||||
cytoscape.use(dagre);
|
||||
|
||||
let callEffect = () => {
|
||||
|
||||
const cytoscapeStylesheet = [
|
||||
{
|
||||
selector: "node",
|
||||
style: {
|
||||
padding: "10px",
|
||||
shape: "round-rectangle",
|
||||
content: "data(id)",
|
||||
"background-color": "darkblue",//"data(color)",
|
||||
"text-wrap": "wrap",
|
||||
"text-max-width": 40,
|
||||
"z-index": 1,
|
||||
},
|
||||
},
|
||||
{
|
||||
selector: "node[id]",
|
||||
style: {
|
||||
label: "data(id)",
|
||||
"font-size": "9",
|
||||
color: "white",//"data(labelColor)",
|
||||
"text-halign": "center",
|
||||
"text-valign": "center",
|
||||
"z-index": 1,
|
||||
},
|
||||
},
|
||||
{
|
||||
selector: "edge",
|
||||
style: {
|
||||
"curve-style": "unbundled-bezier",
|
||||
"target-arrow-shape": "vee",
|
||||
width: 1.5,
|
||||
"target-arrow-color": "darkblue",
|
||||
"arrow-scale": 1.3,
|
||||
"lineColor": "darkblue",
|
||||
"target-arrow-fill": "filled",
|
||||
"text-rotation": "autorotate",
|
||||
"z-index": 0,
|
||||
},
|
||||
},
|
||||
{
|
||||
selector: "edge[label]",
|
||||
style: {
|
||||
label: "data(label)",
|
||||
"font-size": "9",
|
||||
|
||||
"text-background-color": "#f9f9f9",
|
||||
"text-background-opacity": 1,
|
||||
"text-background-padding": "3px",
|
||||
|
||||
"text-border-color": "black",
|
||||
"text-border-style": "solid",
|
||||
"text-border-width": 0.5,
|
||||
"text-border-opacity": 1,
|
||||
"z-index": 3,
|
||||
},
|
||||
},
|
||||
];
|
||||
|
||||
let { nodeElements, edgeElements } = createGraph();
|
||||
setNodeElements(nodeElements)
|
||||
setEdgeElements(edgeElements)
|
||||
|
||||
const config = {
|
||||
container: containerRef.current,
|
||||
style: cytoscapeStylesheet,
|
||||
elements: [...nodeElements, ...edgeElements],
|
||||
layout: {
|
||||
name: "dagre", // circle, grid, dagre
|
||||
minDist: 20,
|
||||
rankDir: "BT",
|
||||
//prelayout: false,
|
||||
// animate: false, // whether to transition the node positions
|
||||
// animationDuration: 250, // duration of animation in ms if enabled
|
||||
// the cytoscape documentation is pretty good here.
|
||||
},
|
||||
userZoomingEnabled: false,
|
||||
userPanningEnabled: false,
|
||||
};
|
||||
|
||||
let newCs = cytoscape(config);
|
||||
setCs(newCs);
|
||||
// cy.layout({ name: 'dagre', rankDir: "BT"}).run()
|
||||
|
||||
// setTimeout(() => setVisibility(""), 700);
|
||||
// necessary for themes like spread, which have
|
||||
// a confusing animation at the beginning
|
||||
|
||||
|
||||
};
|
||||
useEffect(() => {
|
||||
callEffect({
|
||||
});
|
||||
}, [selectedElement]);
|
||||
|
||||
useEffect(() => {
|
||||
if (cs != null) {
|
||||
setTimeout(() => {
|
||||
/*
|
||||
cs.edges().on("click", (event) => {
|
||||
clearTimeout(selectedElementTimeout);
|
||||
let edge = event.target;
|
||||
console.log(JSON.stringify(edge.json()));
|
||||
let newTimeout = setTimeout(() => {
|
||||
let
|
||||
setSelectedElement(JSON.parse(JSON.stringify(edge.json())).data)
|
||||
});
|
||||
setSelectedElementTimeout(newTimeout)
|
||||
});*/
|
||||
cs.nodes().on("click", (event) => {
|
||||
clearTimeout(selectedElementTimeout);
|
||||
let node = event.target;
|
||||
console.log(JSON.stringify(node.json()));
|
||||
let newTimeout = setTimeout(() => {
|
||||
let selectedElementIncomplete = (JSON.parse(JSON.stringify(node.json())).data)
|
||||
let selectedElementName = selectedElementIncomplete.name
|
||||
let selectedElementInFull = nodeElements.filter(node => node.data.name == selectedElementName)
|
||||
console.log("selectedElementInFull", selectedElementInFull)
|
||||
if(selectedElementInFull.length == 1){
|
||||
let elementToBeSelected = selectedElementInFull[0]
|
||||
console.log("elementToBeSelected", elementToBeSelected)
|
||||
setSelectedElement(elementToBeSelected.data)
|
||||
}
|
||||
// setSelectedElement()
|
||||
});
|
||||
setSelectedElementTimeout(newTimeout)
|
||||
});
|
||||
|
||||
}, 100)
|
||||
}
|
||||
}, [cs]);
|
||||
|
||||
|
||||
/*
|
||||
useEffect(() => {
|
||||
if (cs != null) {
|
||||
clearTimeout(selectedElementTimeout);
|
||||
let newTimeout = setTimeout(() => {
|
||||
cs.edges().on("mouseover", (event) => {
|
||||
// on("click",
|
||||
let edge = event.target;
|
||||
// alert(JSON.stringify(edge.json()));
|
||||
console.log(JSON.stringify(edge.json()));
|
||||
setSelectedElement(JSON.parse(JSON.stringify(edge.json())).data);
|
||||
});
|
||||
cs.nodes().on("mouseover", (event) => {
|
||||
// on("click",
|
||||
let node = event.target;
|
||||
// alert(JSON.stringify(edge.json()));
|
||||
console.log(JSON.stringify(node.json()));
|
||||
setSelectedElement(JSON.parse(JSON.stringify(node.json())).data);
|
||||
});
|
||||
}, 100);
|
||||
setSelectedElementTimeout(newTimeout);
|
||||
}
|
||||
}, [cs]);
|
||||
*/
|
||||
return (
|
||||
<div className="grid place-items-center">
|
||||
<div
|
||||
className={
|
||||
`grid grid-cols-${selectedElement == null ? "1 " : "2"
|
||||
}
|
||||
place-items-center place-self-center space-x-0 w-10/12 `
|
||||
}
|
||||
>
|
||||
<div
|
||||
ref={containerRef}
|
||||
style={{
|
||||
height: "900px", // isListOrdered ? "900px" : "500px",
|
||||
width: "900px", // isListOrdered ? "900px" : "500px",
|
||||
}}
|
||||
className=""
|
||||
/>
|
||||
<DynamicSquiggleChart
|
||||
element={selectedElement}
|
||||
stopShowing={() => setSelectedElement(null)}
|
||||
/>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
);
|
||||
|
||||
}
|
15
components/homepage.js
Normal file
|
@ -0,0 +1,15 @@
|
|||
import React, { useState } from "react";
|
||||
|
||||
import { Title } from "./title.js";
|
||||
import { Graph } from "./graph/graph.js";
|
||||
|
||||
|
||||
export function Homepage({ listOfElementsInit }) {
|
||||
|
||||
return (
|
||||
<div className="block w-full items-center sm:w-full mt-10">
|
||||
<Title />
|
||||
<Graph/>
|
||||
</div>
|
||||
);
|
||||
}
|
5
components/title.js
Normal file
|
@ -0,0 +1,5 @@
|
|||
import React, { useState } from "react";
|
||||
|
||||
export function Title() {
|
||||
return <h1 className="text-6xl font-bold ">Hierarchical Estimates Visualizer</h1>;
|
||||
}
|
Before Width: | Height: | Size: 289 KiB After Width: | Height: | Size: 289 KiB |
Before Width: | Height: | Size: 294 KiB After Width: | Height: | Size: 294 KiB |
Before Width: | Height: | Size: 336 KiB After Width: | Height: | Size: 336 KiB |
Before Width: | Height: | Size: 282 KiB After Width: | Height: | Size: 282 KiB |
Before Width: | Height: | Size: 266 KiB After Width: | Height: | Size: 266 KiB |
Before Width: | Height: | Size: 294 KiB After Width: | Height: | Size: 294 KiB |
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "utility-function-extractor",
|
||||
"version": "0.6.1",
|
||||
"name": "hierarchical-estimates-visualizer",
|
||||
"version": "0.0.1",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"dev": "next dev",
|
||||
|
@ -23,11 +23,8 @@
|
|||
"path": "^0.12.7",
|
||||
"react": "^18.0.1",
|
||||
"react-code-blocks": "^0.0.9-0",
|
||||
"react-compound-slider": "^3.3.1",
|
||||
"react-dom": "^18.0.1",
|
||||
"react-markdown": "^6.0.2",
|
||||
"remark-gfm": "^1.0.0",
|
||||
"simple-react-cytoscape": "^1.0.4",
|
||||
"utility-tools": "^1.0.4"
|
||||
},
|
||||
"devDependencies": {
|
|
@ -1,62 +0,0 @@
|
|||
# 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).
|
||||
|
||||
## Built with
|
||||
|
||||
- [Squiggle](https://www.squiggle-language.com/)
|
||||
- [Nodejs](https://nodejs.org/)
|
||||
- Plain js
|
||||
|
||||
## 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.
|
||||
|
||||
_Note_: The `findPaths.js` file has a few un-used functions which should make it easier to understand the code.
|
||||
|
||||
### 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,241 +0,0 @@
|
|||
[
|
||||
{
|
||||
"source": "Stanford University — Machine Learning Security Research Led by Dan Boneh and Florian Tramer",
|
||||
|
||||
"target": "Wilson Center — AI Policy Seminar Series",
|
||||
|
||||
"distance": 4.039836724233664,
|
||||
|
||||
"reasoning": "Jaime's estimates.\nThe Wilson Center seems to not be running the AI Policy Seminar Series anymore, so I am led to believe it was not a great success (?). There could be someone key influenced that will facilitate things later but seems unlikely\nThe ML Security program does not seem to have resulted on anything substantial",
|
||||
|
||||
"squiggleString": "1 to 10"
|
||||
},
|
||||
|
||||
{
|
||||
"source": "Stanford University — Machine Learning Security Research Led by Dan Boneh and Florian Tramer",
|
||||
|
||||
"target": "Open Phil AI Fellowship — 2018 Class",
|
||||
|
||||
"distance": 657.4661082204123,
|
||||
|
||||
"reasoning": "The AI fellows have produced work on interpretability and out of distribution learning.\nSeems to have been better for purchasing influence too, though that's a secondary consideration IMO",
|
||||
|
||||
"squiggleString": "400 to 1000"
|
||||
},
|
||||
|
||||
{
|
||||
"source": "Wilson Center — AI Policy Seminar Series",
|
||||
|
||||
"target": "Open Phil AI Fellowship — 2018 Class",
|
||||
|
||||
"distance": 403.9836724233662,
|
||||
|
||||
"reasoning": "The research seems more directly relevant from the AI fellows, the policy seminar has no legible output",
|
||||
|
||||
"squiggleString": "100 to 1000"
|
||||
},
|
||||
|
||||
{
|
||||
"source": "UC Berkeley — AI Safety Research (2018)",
|
||||
|
||||
"target": "Machine Intelligence Research Institute — AI Safety Retraining Program",
|
||||
|
||||
"distance": 40.39836724233665,
|
||||
|
||||
"reasoning": "Seems to support directly people working on the topic, and more counterfactual",
|
||||
|
||||
"squiggleString": "10 to 100"
|
||||
},
|
||||
|
||||
{
|
||||
"source": "Stanford University — Machine Learning Security Research Led by Dan Boneh and Florian Tramer",
|
||||
|
||||
"target": "UC Berkeley — AI Safety Research (2018)",
|
||||
|
||||
"distance": 7.229755173700019,
|
||||
|
||||
"reasoning": "AI Safety Research Affects more people, someone might end up doing something cool",
|
||||
|
||||
"squiggleString": "5 to 10"
|
||||
},
|
||||
|
||||
{
|
||||
"source": "Wilson Center — AI Policy Seminar Series",
|
||||
|
||||
"target": "UC Berkeley — AI Safety Research (2018)",
|
||||
|
||||
"distance": 2.663515640351876,
|
||||
|
||||
"reasoning": "Similar value from the outside",
|
||||
|
||||
"squiggleString": "0.1 to 10"
|
||||
},
|
||||
|
||||
{
|
||||
"source": "UC Berkeley — AI Safety Research (2018)",
|
||||
|
||||
"target": "Open Phil AI Fellowship — 2018 Class",
|
||||
|
||||
"distance": 247.53475654135346,
|
||||
|
||||
"reasoning": "AI fellows produced directly relevant research, are more successful",
|
||||
|
||||
"squiggleString": "(1/(0.001 to 0.01))"
|
||||
},
|
||||
|
||||
{
|
||||
"source": "Machine Intelligence Research Institute — AI Safety Retraining Program",
|
||||
|
||||
"target": "Open Phil AI Fellowship — 2018 Class",
|
||||
|
||||
"distance": 49.50695130827075,
|
||||
|
||||
"reasoning": "aI fellows seem to have produced more relevant research, though grant is less counterfactual",
|
||||
|
||||
"squiggleString": "(1/(0.005 to 0.05))"
|
||||
},
|
||||
|
||||
{
|
||||
"source": "Ought — General Support (2018)",
|
||||
|
||||
"target": "Oxford University — Research on the Global Politics of AI",
|
||||
|
||||
"distance": 403.9836724233662,
|
||||
|
||||
"reasoning": "GovAI is doing cool stuff, Ought not so much",
|
||||
|
||||
"squiggleString": "100 to 1000"
|
||||
},
|
||||
|
||||
{
|
||||
"source": "AI Impacts — General Support (2018)",
|
||||
|
||||
"target": "Michael Cohen and Dmitrii Krasheninnikov — Scholarship Support (2018)",
|
||||
|
||||
"distance": 2.5202870466776885,
|
||||
|
||||
"reasoning": "Direct work seems more important, but Ai impacts work is pretty cool",
|
||||
|
||||
"squiggleString": "1 to 5"
|
||||
},
|
||||
|
||||
{
|
||||
"source": "Ought — General Support (2018)",
|
||||
|
||||
"target": "AI Impacts — General Support (2018)",
|
||||
|
||||
"distance": 109.28343925564944,
|
||||
|
||||
"reasoning": "AI impacts work has been more successful \\ useful for my research",
|
||||
|
||||
"squiggleString": "50 to 200"
|
||||
},
|
||||
|
||||
{
|
||||
"source": "AI Impacts — General Support (2018)",
|
||||
|
||||
"target": "Oxford University — Research on the Global Politics of AI",
|
||||
|
||||
"distance": 39.678020061969825,
|
||||
|
||||
"reasoning": "GovAI is doing more work and on a more neglected topic. Both are doing good work, but GOvAI output is bigger",
|
||||
|
||||
"squiggleString": "(1/(0.01 to 0.05))"
|
||||
},
|
||||
|
||||
{
|
||||
"source": "Oxford University — Research on the Global Politics of AI",
|
||||
|
||||
"target": "Michael Cohen and Dmitrii Krasheninnikov — Scholarship Support (2018)",
|
||||
|
||||
"distance": 2.865987655844147,
|
||||
|
||||
"reasoning": "Cohens work seems harder to replace.\nGovAI is doing more work though",
|
||||
|
||||
"squiggleString": "0.01 to 10"
|
||||
},
|
||||
|
||||
{
|
||||
"source": "Stanford University — Machine Learning Security Research Led by Dan Boneh and Florian Tramer",
|
||||
|
||||
"target": "Ought — General Support (2018)",
|
||||
|
||||
"distance": 14.338510859889407,
|
||||
|
||||
"reasoning": "At least Ought is trying ",
|
||||
|
||||
"squiggleString": "1 to 50"
|
||||
},
|
||||
|
||||
{
|
||||
"source": "Wilson Center — AI Policy Seminar Series",
|
||||
|
||||
"target": "Ought — General Support (2018)",
|
||||
|
||||
"distance": 2.663515640351876,
|
||||
|
||||
"reasoning": "Unclear",
|
||||
|
||||
"squiggleString": "0.1 to 10"
|
||||
},
|
||||
|
||||
{
|
||||
"source": "UC Berkeley — AI Safety Research (2018)",
|
||||
|
||||
"target": "Ought — General Support (2018)",
|
||||
|
||||
"distance": 4.039836724233664,
|
||||
|
||||
"reasoning": "At least ought is trying",
|
||||
|
||||
"squiggleString": "1 to 10"
|
||||
},
|
||||
|
||||
{
|
||||
"source": "Machine Intelligence Research Institute — AI Safety Retraining Program",
|
||||
|
||||
"target": "Ought — General Support (2018)",
|
||||
|
||||
"distance": 1.4338510859889406,
|
||||
|
||||
"reasoning": "Value more the potential new hire than oughts research",
|
||||
|
||||
"squiggleString": "0.1 to 5"
|
||||
},
|
||||
|
||||
{
|
||||
"source": "Ought — General Support (2018)",
|
||||
|
||||
"target": "Open Phil AI Fellowship — 2018 Class",
|
||||
|
||||
"distance": 247.53475654135346,
|
||||
|
||||
"reasoning": "Fellows seem to have produced more relevant research",
|
||||
|
||||
"squiggleString": "(1/(0.001 to 0.01))"
|
||||
},
|
||||
|
||||
{
|
||||
"source": "AI Impacts — General Support (2018)",
|
||||
|
||||
"target": "Open Phil AI Fellowship — 2018 Class",
|
||||
|
||||
"distance": 13.831727022205978,
|
||||
|
||||
"reasoning": "Fellows produced more relevant research, AI impacts work is cool though",
|
||||
|
||||
"squiggleString": "(1/(0.05 to 0.1))"
|
||||
},
|
||||
|
||||
{
|
||||
"source": "Open Phil AI Fellowship — 2018 Class",
|
||||
|
||||
"target": "Oxford University — Research on the Global Politics of AI",
|
||||
|
||||
"distance": 32.87330541102063,
|
||||
|
||||
"reasoning": "GovAI's grant seems moe counterfactual, their work more directly relevant\n",
|
||||
|
||||
"squiggleString": "20 to 50"
|
||||
}
|
||||
]
|
|
@ -1,47 +0,0 @@
|
|||
[
|
||||
{
|
||||
"name": "Michael Cohen and Dmitrii Krasheninnikov — Scholarship Support (2018)",
|
||||
"url": "https://docs.google.com/document/d/1VlN6I4Jauarx-0Fp7AC1ggeQ02AITsN7S56ffAO9NTU/edit#heading=h.jnlrsr63yliq",
|
||||
"amount": "$159k"
|
||||
},
|
||||
{
|
||||
"name": "AI Impacts — General Support (2018)",
|
||||
"url": "https://docs.google.com/document/d/1VlN6I4Jauarx-0Fp7AC1ggeQ02AITsN7S56ffAO9NTU/edit#heading=h.6m6tebpouzt1",
|
||||
"amount": "$100k"
|
||||
},
|
||||
{
|
||||
"name": "Oxford University — Research on the Global Politics of AI",
|
||||
"url": "https://docs.google.com/document/d/1VlN6I4Jauarx-0Fp7AC1ggeQ02AITsN7S56ffAO9NTU/edit#heading=h.c6r2m7i749ay",
|
||||
"amount": "$429k"
|
||||
},
|
||||
{
|
||||
"name": "Ought — General Support (2018)",
|
||||
"url": "https://docs.google.com/document/d/1VlN6I4Jauarx-0Fp7AC1ggeQ02AITsN7S56ffAO9NTU/edit#heading=h.xnzaj48k3fdb",
|
||||
"amount": "$525k"
|
||||
},
|
||||
{
|
||||
"name": "Machine Intelligence Research Institute — AI Safety Retraining Program",
|
||||
"url": "https://docs.google.com/document/d/1VlN6I4Jauarx-0Fp7AC1ggeQ02AITsN7S56ffAO9NTU/edit#heading=h.h922w7eh5rq6",
|
||||
"amount": "$150k"
|
||||
},
|
||||
{
|
||||
"name": "UC Berkeley — AI Safety Research (2018)",
|
||||
"url": "https://docs.google.com/document/d/1VlN6I4Jauarx-0Fp7AC1ggeQ02AITsN7S56ffAO9NTU/edit#heading=h.rrsbecbboed8",
|
||||
"amount": "$1.145M"
|
||||
},
|
||||
{
|
||||
"name": "Open Phil AI Fellowship — 2018 Class",
|
||||
"url": "https://docs.google.com/document/d/1VlN6I4Jauarx-0Fp7AC1ggeQ02AITsN7S56ffAO9NTU/edit#heading=h.p8xd58asz6a2",
|
||||
"amount": "$1.135M"
|
||||
},
|
||||
{
|
||||
"name": "Wilson Center — AI Policy Seminar Series",
|
||||
"url": "https://docs.google.com/document/d/1VlN6I4Jauarx-0Fp7AC1ggeQ02AITsN7S56ffAO9NTU/edit#heading=h.qiurhycylgi3",
|
||||
"amount": "$400k"
|
||||
},
|
||||
{
|
||||
"name": "Stanford University — Machine Learning Security Research Led by Dan Boneh and Florian Tramer",
|
||||
"url": "https://docs.google.com/document/d/1VlN6I4Jauarx-0Fp7AC1ggeQ02AITsN7S56ffAO9NTU/edit#heading=h.ox8adhpgba86",
|
||||
"amount": "$100k"
|
||||
}
|
||||
]
|
|
@ -1,95 +0,0 @@
|
|||
Sorted output:
|
||||
[
|
||||
'Stanford University — Machine Learning Security Research Led by Dan Boneh and Florian Tramer',
|
||||
'Wilson Center — AI Policy Seminar Series',
|
||||
'UC Berkeley — AI Safety Research (2018)',
|
||||
'Machine Intelligence Research Institute — AI Safety Retraining Program',
|
||||
'Ought — General Support (2018)',
|
||||
'AI Impacts — General Support (2018)',
|
||||
'Open Phil AI Fellowship — 2018 Class',
|
||||
'Oxford University — Research on the Global Politics of AI',
|
||||
'Michael Cohen and Dmitrii Krasheninnikov — Scholarship Support (2018)'
|
||||
]
|
||||
|
||||
Stanford University — Machine Learning Security Research Led by Dan Boneh and Florian Tramer
|
||||
Number of paths: 102
|
||||
Mean: 0.04340463625937361
|
||||
90% confidence interval: [
|
||||
3.102187977841675e-7,
|
||||
0.10636313508232977
|
||||
]
|
||||
3.902 seconds needed for processing
|
||||
|
||||
Wilson Center — AI Policy Seminar Series
|
||||
Number of paths: 52
|
||||
Mean: 0.23923636834715892
|
||||
90% confidence interval: [
|
||||
0.0000012797707857581555,
|
||||
0.7647175734237982
|
||||
]
|
||||
0.855 seconds needed for processing
|
||||
|
||||
UC Berkeley — AI Safety Research (2018)
|
||||
Number of paths: 37
|
||||
Mean: 0.6148765126821536
|
||||
90% confidence interval: [
|
||||
0.0000012857319777641759,
|
||||
2.4285898907477064
|
||||
]
|
||||
0.484 seconds needed for processing
|
||||
|
||||
Machine Intelligence Research Institute — AI Safety Retraining Program
|
||||
Number of paths: 21
|
||||
Mean: 46.33576477417035
|
||||
90% confidence interval: [
|
||||
0.000022241280559831212,
|
||||
201.37264605399085
|
||||
]
|
||||
0.173 seconds needed for processing
|
||||
|
||||
Ought — General Support (2018)
|
||||
Number of paths: 36
|
||||
Mean: 63.37826067838051
|
||||
90% confidence interval: [
|
||||
0.00004411196776834627,
|
||||
145.5050535108514
|
||||
]
|
||||
0.412 seconds needed for processing
|
||||
|
||||
AI Impacts — General Support (2018)
|
||||
Number of paths: 47
|
||||
Mean: 9862.157135402398
|
||||
90% confidence interval: [
|
||||
0.018650934888088284,
|
||||
22307.090052203544
|
||||
]
|
||||
0.635 seconds needed for processing
|
||||
|
||||
Open Phil AI Fellowship — 2018 Class
|
||||
Number of paths: 372
|
||||
Mean: 86301.01328794319
|
||||
90% confidence interval: [
|
||||
26.02179139839112,
|
||||
115734.18190287006
|
||||
]
|
||||
35.203 seconds needed for processing
|
||||
|
||||
Oxford University — Research on the Global Politics of AI
|
||||
Number of paths: 2261
|
||||
Mean: 785779.6653748289
|
||||
90% confidence interval: [
|
||||
114.32195138741375,
|
||||
960250.7929788446
|
||||
]
|
||||
1048.955 seconds needed for processing
|
||||
|
||||
Michael Cohen and Dmitrii Krasheninnikov — Scholarship Support (2018)
|
||||
Number of paths: 5243
|
||||
Mean: 1482642.2273006735
|
||||
90% confidence interval: [
|
||||
8.379381400123396,
|
||||
330071.1150485886
|
||||
]
|
||||
5550.563 seconds needed for processing
|
||||
|
||||
|
|
@ -1,16 +0,0 @@
|
|||
{
|
||||
"name": "utility-tools",
|
||||
"version": "1.0.5",
|
||||
"description": "Process the json produced by utility-function-extractor.quantifieduncertainty.org",
|
||||
"scripts": {
|
||||
"start": "node --max-old-space-size=8192 src/index.js",
|
||||
"example": "node --max-old-space-size=8192 src/example.js"
|
||||
},
|
||||
"type": "module",
|
||||
"main": "src/index.js",
|
||||
"author": "Nuño Sempere",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@quri/squiggle-lang": "^0.2.11"
|
||||
}
|
||||
}
|
|
@ -1,163 +0,0 @@
|
|||
// EXPORTS
|
||||
import { run } from "@quri/squiggle-lang";
|
||||
|
||||
export async function aggregatePathsThroughMixtureOfDistributions({
|
||||
pathsArray,
|
||||
orderedList,
|
||||
VERBOSE,
|
||||
}) {
|
||||
let print = (x) => {
|
||||
if (VERBOSE) {
|
||||
console.log(x);
|
||||
}
|
||||
};
|
||||
let result = pathsArray.map((paths, i) => {
|
||||
print(orderedList[i].name);
|
||||
let multipliedDistributions = paths.map(
|
||||
(path) => path.multipliedDistributionsInPath
|
||||
);
|
||||
console.group();
|
||||
print("Number of paths: ", multipliedDistributions.length);
|
||||
let squiggleCode = `aggregatePath = mx(${multipliedDistributions
|
||||
.filter((distributions) => distributions != undefined)
|
||||
.join(", ")})`;
|
||||
|
||||
// Start measuring time
|
||||
let start = Date.now();
|
||||
|
||||
// Get the mean
|
||||
let squiggleCodeForMean = squiggleCode + "\n" + "mean(aggregatePath)";
|
||||
let meanAnswer = run(squiggleCodeForMean);
|
||||
let mean = meanAnswer.value.value;
|
||||
print(`Mean: ${mean}`);
|
||||
|
||||
// Get the 90% CI
|
||||
let squiggleCodeFor90CI =
|
||||
squiggleCode +
|
||||
"\n" +
|
||||
"[inv(aggregatePath, 0.05), inv(aggregatePath, 0.95)]";
|
||||
let ci90percentAnswer = run(squiggleCodeFor90CI);
|
||||
|
||||
// Display output
|
||||
let processCI90 = (answer) => {
|
||||
let value = answer.value.value;
|
||||
let lower = value[0].value;
|
||||
let upper = value[1].value;
|
||||
return [lower, upper];
|
||||
};
|
||||
print(
|
||||
`90% confidence interval: ${JSON.stringify(
|
||||
processCI90(ci90percentAnswer),
|
||||
null,
|
||||
4
|
||||
)}`
|
||||
);
|
||||
|
||||
// Stop measuring time
|
||||
let end = Date.now();
|
||||
print(`${(end - start) / 1000} seconds needed for processing`);
|
||||
console.groupEnd();
|
||||
print("");
|
||||
return {
|
||||
name: orderedList[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
|
||||
let result = Math.exp(logavg / n);
|
||||
return result;
|
||||
};
|
||||
|
||||
export function aggregatePathsThroughMixtureOfMeans({
|
||||
pathsArray,
|
||||
orderedList,
|
||||
VERBOSE,
|
||||
DONT_EXCLUDE_INFINITIES_AND_NANS,
|
||||
}) {
|
||||
let print = (x) => {
|
||||
if (VERBOSE) {
|
||||
console.log(x);
|
||||
}
|
||||
};
|
||||
|
||||
let result = pathsArray.map((paths, i) => {
|
||||
print(orderedList[i].name);
|
||||
let expectedRelativeValues = paths.map(
|
||||
(path) => path.expectedRelativeValue
|
||||
);
|
||||
|
||||
let expectedRelativeValuesFiltered = expectedRelativeValues;
|
||||
|
||||
if (!DONT_EXCLUDE_INFINITIES_AND_NANS) {
|
||||
expectedRelativeValuesFiltered = expectedRelativeValues
|
||||
.filter((x) => x != undefined)
|
||||
.filter((x) => !isNaN(x))
|
||||
.filter((x) => isFinite(x))
|
||||
.filter((x) => x != null);
|
||||
}
|
||||
|
||||
let hasPositive = expectedRelativeValuesFiltered.filter((x) => x > 0);
|
||||
let hasNegative = expectedRelativeValuesFiltered.filter((x) => x < 0);
|
||||
let answer;
|
||||
if (hasPositive.length != 0 && hasNegative.length != 0) {
|
||||
answer = avg(expectedRelativeValuesFiltered);
|
||||
} else {
|
||||
if (hasNegative.length == 0) {
|
||||
answer = geomMean(expectedRelativeValuesFiltered);
|
||||
} else {
|
||||
let arrayAsPositive = expectedRelativeValuesFiltered.map((x) => -x);
|
||||
answer = -geomMean(arrayAsPositive);
|
||||
}
|
||||
}
|
||||
return {
|
||||
name: orderedList[i].name,
|
||||
aggregatedMeans: answer,
|
||||
arrayMeans: expectedRelativeValuesFiltered,
|
||||
allPositive: hasNegative.length == 0,
|
||||
};
|
||||
});
|
||||
return result;
|
||||
}
|
||||
|
||||
export async function aggregatePaths({
|
||||
pathsArray,
|
||||
orderedList,
|
||||
aggregationType,
|
||||
VERBOSE,
|
||||
}) {
|
||||
if (aggregationType == "distribution") {
|
||||
if (VERBOSE == undefined) {
|
||||
VERBOSE = true;
|
||||
}
|
||||
console.log("Warning: this may take a long time");
|
||||
return await aggregatePathsThroughMixtureOfDistributions({
|
||||
pathsArray,
|
||||
orderedList,
|
||||
VERBOSE,
|
||||
});
|
||||
} else if (aggregationType == "mean") {
|
||||
return aggregatePathsThroughMixtureOfMeans({
|
||||
pathsArray,
|
||||
orderedList,
|
||||
VERBOSE,
|
||||
});
|
||||
} else {
|
||||
return aggregatePathsThroughMixtureOfMeans({
|
||||
pathsArray,
|
||||
orderedList,
|
||||
VERBOSE,
|
||||
});
|
||||
}
|
||||
}
|
|
@ -1,56 +0,0 @@
|
|||
// IMPORTS
|
||||
import * as fs from "fs";
|
||||
import { mergeSort } from "./mergeSort.js";
|
||||
import { findDistances } from "./findPaths.js";
|
||||
import { aggregatePaths } from "./aggregatePaths.js";
|
||||
|
||||
// DEFS
|
||||
const inputLinksFilePath = "./input/input-links-daniel.json";
|
||||
const inputListFilePath = "./input/input-list.json";
|
||||
const outputFilePath = "./output/output.json";
|
||||
|
||||
// HELPERS
|
||||
|
||||
// MAIN
|
||||
async function main() {
|
||||
// Read file
|
||||
const inputLinksAsString = fs.readFileSync(inputLinksFilePath);
|
||||
const inputListAsString = fs.readFileSync(inputListFilePath);
|
||||
const links = JSON.parse(inputLinksAsString);
|
||||
const list = JSON.parse(inputListAsString);
|
||||
|
||||
// Merge sort
|
||||
let mergeSortOutput = mergeSort({
|
||||
list,
|
||||
links,
|
||||
tryHardWithPermutations: true,
|
||||
});
|
||||
if (mergeSortOutput.finishedOrderingList == false) {
|
||||
console.log("Merge could not proceed");
|
||||
console.group();
|
||||
console.log("Elements which need to be compared:");
|
||||
console.log(mergeSortOutput.uncomparedElements);
|
||||
console.groupEnd();
|
||||
} else {
|
||||
let orderedList = mergeSortOutput.orderedList;
|
||||
console.log("Sorted output: ");
|
||||
console.group();
|
||||
console.log(orderedList.map((x) => x.name));
|
||||
console.groupEnd();
|
||||
console.log("");
|
||||
|
||||
// find Paths
|
||||
let paths = await findDistances({ orderedList, links });
|
||||
|
||||
// Aggregate paths.
|
||||
let aggregatedPaths = await aggregatePaths({
|
||||
pathsArray: paths,
|
||||
orderedList,
|
||||
aggregationType: "distribution", // alternatively: aggregationType: "distribution" | "mean"
|
||||
VERBOSE: true, // optional arg
|
||||
DONT_EXCLUDE_INFINITIES_AND_NANS: false, // optional arg
|
||||
});
|
||||
console.log(aggregatedPaths);
|
||||
}
|
||||
}
|
||||
main();
|
|
@ -1,283 +0,0 @@
|
|||
/* Functions */
|
||||
|
||||
const pathPlusLink = (pathSoFar, link) => {
|
||||
return [...pathSoFar, link];
|
||||
// previously: pathSoFar.concat(link).flat()
|
||||
// Note that concat is not destructive
|
||||
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/concat
|
||||
};
|
||||
|
||||
const findElementPosition = (name, nodes) => {
|
||||
let node = nodes.find((node) => node.name == name);
|
||||
return node.position;
|
||||
};
|
||||
|
||||
async function findPathsWithoutPrunning({
|
||||
// DO NOT DELETE THIS UN-USED FUNCTION
|
||||
// USEFUL FOR UNDERSTANDING AGAIN HOW THIS CODE WORKS AFTER A FEW MONTHS
|
||||
sourceElementName,
|
||||
targetElementName,
|
||||
maxLengthOfPath,
|
||||
pathSoFar,
|
||||
links,
|
||||
nodes,
|
||||
}) {
|
||||
// This is an un-used function which might make findPaths more understandable
|
||||
// It uses the same recursive functionality
|
||||
// but has no path prunning
|
||||
let paths = [];
|
||||
|
||||
/* Path traversing */
|
||||
if (maxLengthOfPath > 0) {
|
||||
for (let link of links) {
|
||||
// vs let link of linksNow in findPaths
|
||||
if (
|
||||
(link.source == sourceElementName &&
|
||||
link.target == targetElementName) ||
|
||||
(link.source == targetElementName && link.target == sourceElementName)
|
||||
) {
|
||||
// direct Path
|
||||
let newPath = pathPlusLink(pathSoFar, link);
|
||||
paths.push(newPath);
|
||||
} else if (link.source == sourceElementName) {
|
||||
let newPaths = await findPaths({
|
||||
pathSoFar: pathPlusLink(pathSoFar, link),
|
||||
maxLengthOfPath: maxLengthOfPath - 1,
|
||||
sourceElementName: link.target,
|
||||
targetElementName,
|
||||
links: links, // vs let link of linksInner in findPaths
|
||||
nodes,
|
||||
});
|
||||
if (newPaths.length != 0) {
|
||||
paths.push(...newPaths);
|
||||
}
|
||||
} else if (link.target == sourceElementName) {
|
||||
let newPaths = await findPaths({
|
||||
pathSoFar: pathPlusLink(pathSoFar, link),
|
||||
maxLengthOfPath: maxLengthOfPath - 1,
|
||||
sourceElementName: link.source,
|
||||
targetElementName,
|
||||
links: links, // vs let link of linksInner in findPaths
|
||||
nodes,
|
||||
});
|
||||
if (newPaths.length != 0) {
|
||||
paths.push(...newPaths);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return paths;
|
||||
}
|
||||
|
||||
async function findPaths({
|
||||
sourceElementName,
|
||||
sourceElementPosition,
|
||||
targetElementName,
|
||||
targetElementPosition,
|
||||
maxLengthOfPath,
|
||||
pathSoFar,
|
||||
links,
|
||||
nodes,
|
||||
}) {
|
||||
// This is the key path finding function
|
||||
// It finds the path from one element to another, recursively
|
||||
// It used to be very computationally expensive until I added
|
||||
// the path prunning step: Instead of traversing all links,
|
||||
// traverse only those which are between the origin and target links
|
||||
// this requires us to have a notion of "between"
|
||||
|
||||
let paths = [];
|
||||
|
||||
/* Path prunning*/
|
||||
let minPos = Math.min(sourceElementPosition, targetElementPosition);
|
||||
let maxPos = Math.max(sourceElementPosition, targetElementPosition);
|
||||
let linksInner = links.filter(
|
||||
(link) =>
|
||||
minPos <= link.sourceElementPosition &&
|
||||
link.sourceElementPosition <= maxPos &&
|
||||
minPos <= link.targetElementPosition &&
|
||||
link.targetElementPosition <= maxPos
|
||||
);
|
||||
let linksNow = linksInner.filter(
|
||||
(link) =>
|
||||
link.source == sourceElementName || link.target == sourceElementName
|
||||
);
|
||||
|
||||
/* Path traversing */
|
||||
if (maxLengthOfPath > 0) {
|
||||
for (let link of linksNow) {
|
||||
if (
|
||||
(link.source == sourceElementName &&
|
||||
link.target == targetElementName) ||
|
||||
(link.source == targetElementName && link.target == sourceElementName)
|
||||
) {
|
||||
// We have found a direct path.
|
||||
let newPath = pathPlusLink(pathSoFar, link);
|
||||
paths.push(newPath);
|
||||
} else if (link.source == sourceElementName) {
|
||||
// Recursively call find Paths
|
||||
let newPaths = await findPaths({
|
||||
pathSoFar: pathPlusLink(pathSoFar, link),
|
||||
maxLengthOfPath: maxLengthOfPath - 1,
|
||||
sourceElementPosition: link.sourceElementPosition,
|
||||
sourceElementName: link.target,
|
||||
targetElementName,
|
||||
targetElementPosition,
|
||||
links: linksInner,
|
||||
nodes,
|
||||
});
|
||||
if (newPaths.length != 0) {
|
||||
paths.push(...newPaths);
|
||||
}
|
||||
} else if (link.target == sourceElementName) {
|
||||
let newPaths = await findPaths({
|
||||
pathSoFar: pathPlusLink(pathSoFar, link),
|
||||
maxLengthOfPath: maxLengthOfPath - 1,
|
||||
sourceElementPosition: link.sourceElementPosition,
|
||||
sourceElementName: link.source,
|
||||
targetElementPosition,
|
||||
targetElementName,
|
||||
links: linksInner,
|
||||
nodes,
|
||||
});
|
||||
if (newPaths.length != 0) {
|
||||
paths.push(...newPaths);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return paths;
|
||||
}
|
||||
|
||||
async function findExpectedValuesAndDistributionsForElement({
|
||||
sourceElementName,
|
||||
sourceElementPosition,
|
||||
targetElementName,
|
||||
targetElementPosition,
|
||||
nodes,
|
||||
links,
|
||||
}) {
|
||||
// This function gets all possible paths using findPaths
|
||||
// then orders them correctly in the for loop
|
||||
// (by flipping the distance to 1/distance when necessary)
|
||||
// and then gets the array of weights for the different paths.
|
||||
|
||||
let maxLengthOfPath = Math.abs(sourceElementPosition - targetElementPosition);
|
||||
let paths = await findPaths({
|
||||
sourceElementName,
|
||||
sourceElementPosition,
|
||||
targetElementName,
|
||||
targetElementPosition,
|
||||
links,
|
||||
nodes,
|
||||
maxLengthOfPath,
|
||||
pathSoFar: [],
|
||||
});
|
||||
|
||||
let processedPaths = [];
|
||||
for (let path of paths) {
|
||||
let currentSource = sourceElementName;
|
||||
let expectedRelativeValue = 1;
|
||||
let multipliedDistributionsInPath = 1;
|
||||
let distances = [];
|
||||
for (let element of path) {
|
||||
let distance = 0;
|
||||
let anotherDistributionInPath = 1;
|
||||
if (element.source == currentSource) {
|
||||
distance = element.distance;
|
||||
anotherDistributionInPath = element.squiggleString;
|
||||
currentSource = element.target;
|
||||
} else if (element.target == currentSource) {
|
||||
distance = 1 / Number(element.distance);
|
||||
anotherDistributionInPath = `1 / (${element.squiggleString})`;
|
||||
currentSource = element.source;
|
||||
}
|
||||
expectedRelativeValue = expectedRelativeValue * distance;
|
||||
distances.push(distance);
|
||||
multipliedDistributionsInPath = `${multipliedDistributionsInPath} * (${anotherDistributionInPath})`;
|
||||
}
|
||||
processedPaths.push({
|
||||
distances,
|
||||
expectedRelativeValue,
|
||||
multipliedDistributionsInPath,
|
||||
// path,
|
||||
});
|
||||
}
|
||||
return processedPaths;
|
||||
}
|
||||
|
||||
async function findDistancesFromAllElementsToReferencePoint({
|
||||
nodes,
|
||||
links,
|
||||
referenceElement,
|
||||
}) {
|
||||
// Simple wrapper function around findDistance
|
||||
// Needs to find the reference point first
|
||||
// console.log("findDistancesForAllElements@findPaths.js");
|
||||
/* Get or build reference element */
|
||||
let midpoint = Math.round(nodes.length / 2);
|
||||
referenceElement = referenceElement || nodes[midpoint];
|
||||
|
||||
/* Get distances. */
|
||||
let distancesArray = nodes.map((node) => {
|
||||
if (node.name == referenceElement.name) {
|
||||
return [1];
|
||||
} else {
|
||||
let expectedValuesAndDistributionsForElement =
|
||||
findExpectedValuesAndDistributionsForElement({
|
||||
sourceElementName: referenceElement.name,
|
||||
sourceElementPosition: referenceElement.position,
|
||||
targetElementName: node.name,
|
||||
targetElementPosition: node.position,
|
||||
nodes: nodes,
|
||||
links: links,
|
||||
});
|
||||
return expectedValuesAndDistributionsForElement;
|
||||
}
|
||||
});
|
||||
distancesArray = await Promise.all(distancesArray);
|
||||
return distancesArray;
|
||||
}
|
||||
|
||||
export async function findDistancesFromAllElementsToAllReferencePoints({
|
||||
nodes,
|
||||
links,
|
||||
}) {
|
||||
let nodes2 = nodes.map((node) => ({ ...node, isReferenceValue: false }));
|
||||
let distancesForAllElements = Array(nodes.length);
|
||||
for (let i = 0; i < nodes.length; i++) {
|
||||
distancesForAllElements[i] = [];
|
||||
}
|
||||
for (let node of nodes2) {
|
||||
let distancesFromNode = await findDistancesFromAllElementsToReferencePoint({
|
||||
nodes: nodes2,
|
||||
links,
|
||||
referenceElement: node,
|
||||
});
|
||||
distancesForAllElements = distancesForAllElements.map((arr, i) => {
|
||||
return !!arr && arr.length > 0
|
||||
? [...arr, ...distancesFromNode[i]]
|
||||
: distancesFromNode[i];
|
||||
});
|
||||
}
|
||||
return distancesForAllElements;
|
||||
}
|
||||
|
||||
export async function findDistances({ orderedList, links }) {
|
||||
let nodes = orderedList.map((element, i) => ({
|
||||
...element,
|
||||
position: i,
|
||||
}));
|
||||
const linksWithPosition = links.map((link) => ({
|
||||
...link,
|
||||
sourceElementPosition: findElementPosition(link.source, nodes),
|
||||
targetElementPosition: findElementPosition(link.target, nodes),
|
||||
}));
|
||||
let result = await findDistancesFromAllElementsToAllReferencePoints({
|
||||
nodes,
|
||||
links: linksWithPosition,
|
||||
});
|
||||
return result;
|
||||
}
|
|
@ -1,5 +0,0 @@
|
|||
import { mergeSort } from "./mergeSort.js";
|
||||
import { findDistances } from "./findPaths.js";
|
||||
import { aggregatePaths } from "./aggregatePaths.js";
|
||||
|
||||
export { mergeSort, aggregatePaths, findDistances };
|
|
@ -1,208 +0,0 @@
|
|||
const errorMsg = "No link found; unable to proceed";
|
||||
|
||||
function isFirstElementGreater(links, element1, element2) {
|
||||
const relevantComparisons = links.filter(
|
||||
(link) =>
|
||||
(link.source == element1.name && link.target == element2.name) ||
|
||||
(link.source == element2.name && link.target == element1.name)
|
||||
);
|
||||
if (relevantComparisons.length == 0) {
|
||||
let answer = {
|
||||
foundAnswer: false,
|
||||
error: errorMsg,
|
||||
};
|
||||
return answer;
|
||||
} else {
|
||||
const firstLink = relevantComparisons[0];
|
||||
const firstElementFirst =
|
||||
firstLink.source == element1.name && firstLink.target == element2.name
|
||||
? true
|
||||
: false;
|
||||
const distanceIsGreaterThanOne = Number(firstLink.distance) > 1;
|
||||
const isFirstElementFirst =
|
||||
(firstElementFirst && !distanceIsGreaterThanOne) ||
|
||||
(!firstElementFirst && distanceIsGreaterThanOne);
|
||||
let answer = {
|
||||
foundAnswer: true,
|
||||
isFirstElementFirst,
|
||||
errorMsg,
|
||||
};
|
||||
return answer;
|
||||
}
|
||||
}
|
||||
|
||||
function merge(links, left, right) {
|
||||
let sortedArr = [];
|
||||
while (left.length && right.length) {
|
||||
// insert the biggest element to the sortedArr
|
||||
let getComparisonAnswer = isFirstElementGreater(links, left[0], right[0]);
|
||||
if (getComparisonAnswer.foundAnswer == false) {
|
||||
let result = {
|
||||
finishedMerge: false,
|
||||
uncomparedElements: [left[0], right[0]],
|
||||
errorMsg: errorMsg,
|
||||
};
|
||||
return result;
|
||||
} else if (getComparisonAnswer.foundAnswer == true) {
|
||||
if (getComparisonAnswer.isFirstElementFirst == true) {
|
||||
// left[0] > right[0]
|
||||
// note that we can order from smallest to largest or the reverse
|
||||
// ; I forget which one this is.
|
||||
sortedArr.push(right.shift());
|
||||
} else {
|
||||
sortedArr.push(left.shift());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// use spread operator and create a new array, combining the three arrays
|
||||
let result = {
|
||||
finishedMerge: true,
|
||||
orderedList: [...sortedArr, ...left, ...right],
|
||||
// if they don't have the same size, the remaining ones will be greater than the ones before
|
||||
};
|
||||
return result;
|
||||
}
|
||||
|
||||
export function mergeSortInner({ recursiveInput, links }) {
|
||||
if (recursiveInput.bottleneckedByComparison == true) {
|
||||
let result = {
|
||||
recursiveInput: {
|
||||
list: recursiveInput.list,
|
||||
bottleneckedByComparison: true,
|
||||
uncomparedElements: recursiveInput.uncomparedElements,
|
||||
},
|
||||
links: links,
|
||||
};
|
||||
return result;
|
||||
}
|
||||
const half = recursiveInput.list.length / 2;
|
||||
|
||||
// the base case is list length <=1
|
||||
if (recursiveInput.list.length <= 1) {
|
||||
let result = {
|
||||
recursiveInput: {
|
||||
bottleneckedByComparison: false,
|
||||
list: recursiveInput.list,
|
||||
},
|
||||
links: links,
|
||||
};
|
||||
return result;
|
||||
}
|
||||
|
||||
const left = recursiveInput.list.slice(0, half); // the first half of the list
|
||||
const right = recursiveInput.list.slice(half, recursiveInput.list.length); // Note that splice is destructive, and that slice instead creates a new array.
|
||||
let orderedFirstHalfAnswer = mergeSortInner({
|
||||
recursiveInput: { list: left, bottleneckedByComparison: false },
|
||||
links,
|
||||
});
|
||||
let orderedSecondHalfAnswer = mergeSortInner({
|
||||
recursiveInput: { list: right, bottleneckedByComparison: false },
|
||||
links,
|
||||
});
|
||||
if (
|
||||
orderedFirstHalfAnswer.recursiveInput.bottleneckedByComparison == false &&
|
||||
orderedSecondHalfAnswer.recursiveInput.bottleneckedByComparison == false
|
||||
) {
|
||||
let mergeStepAnswer = merge(
|
||||
links,
|
||||
orderedFirstHalfAnswer.recursiveInput.list,
|
||||
orderedSecondHalfAnswer.recursiveInput.list
|
||||
);
|
||||
if (mergeStepAnswer.finishedMerge == true) {
|
||||
let result = {
|
||||
recursiveInput: {
|
||||
list: mergeStepAnswer.orderedList,
|
||||
bottleneckedByComparison: false,
|
||||
},
|
||||
links,
|
||||
};
|
||||
return result;
|
||||
} else {
|
||||
let result = {
|
||||
recursiveInput: {
|
||||
list: recursiveInput.list,
|
||||
bottleneckedByComparison: true,
|
||||
uncomparedElements: mergeStepAnswer.uncomparedElements,
|
||||
},
|
||||
links,
|
||||
};
|
||||
return result;
|
||||
}
|
||||
} else if (
|
||||
orderedFirstHalfAnswer.recursiveInput.bottleneckedByComparison == true
|
||||
) {
|
||||
return orderedFirstHalfAnswer;
|
||||
} else {
|
||||
return orderedSecondHalfAnswer;
|
||||
}
|
||||
}
|
||||
|
||||
export function mergeSort({ list, links, tryHardWithPermutations }) {
|
||||
// Try normally
|
||||
let answer = mergeSortInner({
|
||||
recursiveInput: { list, bottleneckedByComparison: false },
|
||||
links,
|
||||
});
|
||||
if (answer.recursiveInput.bottleneckedByComparison == false) {
|
||||
let result = {
|
||||
finishedOrderingList: true,
|
||||
orderedList: answer.recursiveInput.list,
|
||||
};
|
||||
return result;
|
||||
} else if (tryHardWithPermutations != true) {
|
||||
let result = {
|
||||
finishedOrderingList: false,
|
||||
uncomparedElements: answer.recursiveInput.uncomparedElements,
|
||||
};
|
||||
return result;
|
||||
} else {
|
||||
// otherwise, test all other permutations:
|
||||
let permutation = list.slice();
|
||||
var length = list.length;
|
||||
// let result = [list.slice()];
|
||||
let c = new Array(length).fill(0);
|
||||
let i = 1;
|
||||
let k;
|
||||
let p;
|
||||
let counter = 0;
|
||||
let errorMsg =
|
||||
"Error: The original list was wrongly ordered, and trying permutations didn't work";
|
||||
|
||||
while (i < length) {
|
||||
counter++;
|
||||
if (counter > 10) console.log("permutation #" + counter);
|
||||
if (c[i] < i) {
|
||||
k = i % 2 && c[i];
|
||||
p = permutation[i];
|
||||
permutation[i] = permutation[k];
|
||||
permutation[k] = p;
|
||||
// ++c[i];
|
||||
c[i] = c[i] + 1;
|
||||
i = 1;
|
||||
let answer = mergeSortInner({
|
||||
recursiveInput: {
|
||||
list: permutation,
|
||||
bottleneckedByComparison: false,
|
||||
},
|
||||
links,
|
||||
});
|
||||
if (answer.recursiveInput.bottleneckedByComparison == false) {
|
||||
console.log(answer.recursiveInput);
|
||||
let result = {
|
||||
finishedOrderingList: true,
|
||||
orderedList: answer.recursiveInput.list,
|
||||
};
|
||||
return result;
|
||||
}
|
||||
// result.push(permutation.slice());
|
||||
} else {
|
||||
c[i] = 0;
|
||||
i = i + 1;
|
||||
// ++i;
|
||||
}
|
||||
}
|
||||
console.log(errorMsg);
|
||||
return errorMsg;
|
||||
}
|
||||
}
|
|
@ -1,505 +0,0 @@
|
|||
# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
|
||||
# yarn lockfile v1
|
||||
|
||||
|
||||
"@babel/runtime@^7.18.3":
|
||||
version "7.18.3"
|
||||
resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.18.3.tgz#c7b654b57f6f63cf7f8b418ac9ca04408c4579f4"
|
||||
integrity sha512-38Y8f7YUhce/K7RMwTp7m0uCumpv9hZkitCbBClqQIow1qSbCvGkcegKOXpEWCQLfWmevgRiWokZ1GkpfhbZug==
|
||||
dependencies:
|
||||
regenerator-runtime "^0.13.4"
|
||||
|
||||
"@quri/squiggle-lang@^0.2.11":
|
||||
version "0.2.11"
|
||||
resolved "https://registry.yarnpkg.com/@quri/squiggle-lang/-/squiggle-lang-0.2.11.tgz#fc9df37c1c5537b4da099c71c8249373210cfadf"
|
||||
integrity sha512-n879EbSS0eWWEl+s38XmB4xDy18wOJSk3t7moCxIGDhUc70aH1kgNhg56M+M57a8f55MbIhhr7kAVb9RbqqhuA==
|
||||
dependencies:
|
||||
"@stdlib/stats" "^0.0.13"
|
||||
jstat "^1.9.5"
|
||||
lodash "^4.17.21"
|
||||
mathjs "^10.6.0"
|
||||
pdfast "^0.2.0"
|
||||
rescript "^9.1.4"
|
||||
|
||||
"@stdlib/array@^0.0.x":
|
||||
version "0.0.12"
|
||||
resolved "https://registry.yarnpkg.com/@stdlib/array/-/array-0.0.12.tgz#12f40ab95bb36d424cdad991f29fc3cb491ee29e"
|
||||
integrity sha512-nDksiuvRC1dSTHrf5yOGQmlRwAzSKV8MdFQwFSvLbZGGhi5Y4hExqea5HloLgNVouVs8lnAFi2oubSM4Mc7YAg==
|
||||
dependencies:
|
||||
"@stdlib/assert" "^0.0.x"
|
||||
"@stdlib/blas" "^0.0.x"
|
||||
"@stdlib/complex" "^0.0.x"
|
||||
"@stdlib/constants" "^0.0.x"
|
||||
"@stdlib/math" "^0.0.x"
|
||||
"@stdlib/symbol" "^0.0.x"
|
||||
"@stdlib/types" "^0.0.x"
|
||||
"@stdlib/utils" "^0.0.x"
|
||||
|
||||
"@stdlib/assert@^0.0.x":
|
||||
version "0.0.12"
|
||||
resolved "https://registry.yarnpkg.com/@stdlib/assert/-/assert-0.0.12.tgz#1648c9016e5041291f55a6464abcc4069c5103ce"
|
||||
integrity sha512-38FxFf+ZoQZbdc+m09UsWtaCmzd/2e7im0JOaaFYE7icmRfm+4KiE9BRvBT4tIn7ioLB2f9PsBicKjIsf+tY1w==
|
||||
dependencies:
|
||||
"@stdlib/array" "^0.0.x"
|
||||
"@stdlib/cli" "^0.0.x"
|
||||
"@stdlib/complex" "^0.0.x"
|
||||
"@stdlib/constants" "^0.0.x"
|
||||
"@stdlib/fs" "^0.0.x"
|
||||
"@stdlib/math" "^0.0.x"
|
||||
"@stdlib/ndarray" "^0.0.x"
|
||||
"@stdlib/number" "^0.0.x"
|
||||
"@stdlib/os" "^0.0.x"
|
||||
"@stdlib/process" "^0.0.x"
|
||||
"@stdlib/regexp" "^0.0.x"
|
||||
"@stdlib/streams" "^0.0.x"
|
||||
"@stdlib/string" "^0.0.x"
|
||||
"@stdlib/symbol" "^0.0.x"
|
||||
"@stdlib/types" "^0.0.x"
|
||||
"@stdlib/utils" "^0.0.x"
|
||||
|
||||
"@stdlib/bigint@^0.0.x":
|
||||
version "0.0.11"
|
||||
resolved "https://registry.yarnpkg.com/@stdlib/bigint/-/bigint-0.0.11.tgz#c416a1d727001c55f4897e6424124199d638f2fd"
|
||||
integrity sha512-uz0aYDLABAYyqxaCSHYbUt0yPkXYUCR7TrVvHN+UUD3i8FZ02ZKcLO+faKisDyxKEoSFTNtn3Ro8Ir5ebOlVXQ==
|
||||
dependencies:
|
||||
"@stdlib/utils" "^0.0.x"
|
||||
|
||||
"@stdlib/blas@^0.0.x":
|
||||
version "0.0.12"
|
||||
resolved "https://registry.yarnpkg.com/@stdlib/blas/-/blas-0.0.12.tgz#7e93e42b4621fc6903bf63264f045047333536c2"
|
||||
integrity sha512-nWY749bWceuoWQ7gz977blCwR7lyQ/rsIXVO4b600h+NFpeA2i/ea7MYC680utIbeu2cnDWHdglBPoK535VAzA==
|
||||
dependencies:
|
||||
"@stdlib/array" "^0.0.x"
|
||||
"@stdlib/assert" "^0.0.x"
|
||||
"@stdlib/math" "^0.0.x"
|
||||
"@stdlib/number" "^0.0.x"
|
||||
"@stdlib/types" "^0.0.x"
|
||||
"@stdlib/utils" "^0.0.x"
|
||||
|
||||
"@stdlib/buffer@^0.0.x":
|
||||
version "0.0.11"
|
||||
resolved "https://registry.yarnpkg.com/@stdlib/buffer/-/buffer-0.0.11.tgz#6137b00845e6c905181cc7ebfae9f7e47c01b0ce"
|
||||
integrity sha512-Jeie5eDDa1tVuRcuU+cBXI/oOXSmMxUUccZpqXzgYe0IO8QSNtNxv9mUTzJk/m5wH+lmLoDvNxzPpOH9TODjJg==
|
||||
dependencies:
|
||||
"@stdlib/array" "^0.0.x"
|
||||
"@stdlib/assert" "^0.0.x"
|
||||
"@stdlib/process" "^0.0.x"
|
||||
"@stdlib/types" "^0.0.x"
|
||||
"@stdlib/utils" "^0.0.x"
|
||||
|
||||
"@stdlib/cli@^0.0.x":
|
||||
version "0.0.10"
|
||||
resolved "https://registry.yarnpkg.com/@stdlib/cli/-/cli-0.0.10.tgz#28e2fbe6865d7f5cd15b7dc5846c99bd3b91674f"
|
||||
integrity sha512-OITGaxG46kwK799+NuOd/+ccosJ9koVuQBC610DDJv0ZJf8mD7sbjGXrmue9C4EOh8MP7Vm/6HN14BojX8oTCg==
|
||||
dependencies:
|
||||
"@stdlib/utils" "^0.0.x"
|
||||
minimist "^1.2.0"
|
||||
|
||||
"@stdlib/complex@^0.0.x":
|
||||
version "0.0.12"
|
||||
resolved "https://registry.yarnpkg.com/@stdlib/complex/-/complex-0.0.12.tgz#3afbc190cd0a9b37fc7c6e508c3aa9fda9106944"
|
||||
integrity sha512-UbZBdaUxT2G+lsTIrVlRZwx2IRY6GXnVILggeejsIVxHSuK+oTyapfetcAv0FJFLP+Rrr+ZzrN4b9G3hBw6NHA==
|
||||
dependencies:
|
||||
"@stdlib/array" "^0.0.x"
|
||||
"@stdlib/assert" "^0.0.x"
|
||||
"@stdlib/types" "^0.0.x"
|
||||
"@stdlib/utils" "^0.0.x"
|
||||
|
||||
"@stdlib/constants@^0.0.x":
|
||||
version "0.0.11"
|
||||
resolved "https://registry.yarnpkg.com/@stdlib/constants/-/constants-0.0.11.tgz#78cd56d6c2982b30264843c3d75bde7125e90cd2"
|
||||
integrity sha512-cWKy0L9hXHUQTvFzdPkTvZnn/5Pjv7H4UwY0WC1rLt+A5CxFDJKjvnIi9ypSzJS3CAiGl1ZaHCdadoqXhNdkUg==
|
||||
dependencies:
|
||||
"@stdlib/array" "^0.0.x"
|
||||
"@stdlib/assert" "^0.0.x"
|
||||
"@stdlib/number" "^0.0.x"
|
||||
"@stdlib/utils" "^0.0.x"
|
||||
|
||||
"@stdlib/fs@^0.0.x":
|
||||
version "0.0.12"
|
||||
resolved "https://registry.yarnpkg.com/@stdlib/fs/-/fs-0.0.12.tgz#662365fd5846a51f075724b4f2888ae88441b70d"
|
||||
integrity sha512-zcDLbt39EEM3M3wJW6luChS53B8T+TMJkjs2526UpKJ71O0/0adR57cI7PfCpkMd33d05uM7GM+leEj4eks4Cw==
|
||||
dependencies:
|
||||
"@stdlib/array" "^0.0.x"
|
||||
"@stdlib/assert" "^0.0.x"
|
||||
"@stdlib/cli" "^0.0.x"
|
||||
"@stdlib/math" "^0.0.x"
|
||||
"@stdlib/process" "^0.0.x"
|
||||
"@stdlib/string" "^0.0.x"
|
||||
"@stdlib/utils" "^0.0.x"
|
||||
debug "^2.6.9"
|
||||
|
||||
"@stdlib/math@^0.0.x":
|
||||
version "0.0.11"
|
||||
resolved "https://registry.yarnpkg.com/@stdlib/math/-/math-0.0.11.tgz#eb6638bc03a20fbd6727dd5b977ee0170bda4649"
|
||||
integrity sha512-qI78sR1QqGjHj8k/aAqkZ51Su2fyBvaR/jMKQqcB/ML8bpYpf+QGlGvTty5Qdru/wpqds4kVFOVbWGcNFIV2+Q==
|
||||
dependencies:
|
||||
"@stdlib/assert" "^0.0.x"
|
||||
"@stdlib/constants" "^0.0.x"
|
||||
"@stdlib/ndarray" "^0.0.x"
|
||||
"@stdlib/number" "^0.0.x"
|
||||
"@stdlib/strided" "^0.0.x"
|
||||
"@stdlib/symbol" "^0.0.x"
|
||||
"@stdlib/types" "^0.0.x"
|
||||
"@stdlib/utils" "^0.0.x"
|
||||
debug "^2.6.9"
|
||||
|
||||
"@stdlib/ndarray@^0.0.x":
|
||||
version "0.0.13"
|
||||
resolved "https://registry.yarnpkg.com/@stdlib/ndarray/-/ndarray-0.0.13.tgz#2e8fc645e10f56a645a0ab81598808c0e8f43b82"
|
||||
integrity sha512-Z+U9KJP4U2HWrLtuAXSPvhNetAdqaNLMcliR6S/fz+VPlFDeymRK7omRFMgVQ+1zcAvIgKZGJxpLC3vjiPUYEw==
|
||||
dependencies:
|
||||
"@stdlib/array" "^0.0.x"
|
||||
"@stdlib/assert" "^0.0.x"
|
||||
"@stdlib/bigint" "^0.0.x"
|
||||
"@stdlib/buffer" "^0.0.x"
|
||||
"@stdlib/complex" "^0.0.x"
|
||||
"@stdlib/constants" "^0.0.x"
|
||||
"@stdlib/math" "^0.0.x"
|
||||
"@stdlib/number" "^0.0.x"
|
||||
"@stdlib/string" "^0.0.x"
|
||||
"@stdlib/types" "^0.0.x"
|
||||
"@stdlib/utils" "^0.0.x"
|
||||
|
||||
"@stdlib/nlp@^0.0.x":
|
||||
version "0.0.11"
|
||||
resolved "https://registry.yarnpkg.com/@stdlib/nlp/-/nlp-0.0.11.tgz#532ec0f7267b8d639e4c20c6de864e8de8a09054"
|
||||
integrity sha512-D9avYWANm0Db2W7RpzdSdi5GxRYALGAqUrNnRnnKIO6sMEfr/DvONoAbWruda4QyvSC+0MJNwcEn7+PHhRwYhw==
|
||||
dependencies:
|
||||
"@stdlib/array" "^0.0.x"
|
||||
"@stdlib/assert" "^0.0.x"
|
||||
"@stdlib/math" "^0.0.x"
|
||||
"@stdlib/random" "^0.0.x"
|
||||
"@stdlib/string" "^0.0.x"
|
||||
"@stdlib/utils" "^0.0.x"
|
||||
|
||||
"@stdlib/number@^0.0.x":
|
||||
version "0.0.10"
|
||||
resolved "https://registry.yarnpkg.com/@stdlib/number/-/number-0.0.10.tgz#4030ad8fc3fac19a9afb415c443cee6deea0e65c"
|
||||
integrity sha512-RyfoP9MlnX4kccvg8qv7vYQPbLdzfS1Mnp/prGOoWhvMG3pyBwFAan34kwFb5IS/zHC3W5EmrgXCV2QWyLg/Kg==
|
||||
dependencies:
|
||||
"@stdlib/array" "^0.0.x"
|
||||
"@stdlib/assert" "^0.0.x"
|
||||
"@stdlib/constants" "^0.0.x"
|
||||
"@stdlib/math" "^0.0.x"
|
||||
"@stdlib/os" "^0.0.x"
|
||||
"@stdlib/string" "^0.0.x"
|
||||
"@stdlib/types" "^0.0.x"
|
||||
"@stdlib/utils" "^0.0.x"
|
||||
|
||||
"@stdlib/os@^0.0.x":
|
||||
version "0.0.12"
|
||||
resolved "https://registry.yarnpkg.com/@stdlib/os/-/os-0.0.12.tgz#08bbf013c62a7153099fa9cbac086ca1349a4677"
|
||||
integrity sha512-O7lklZ/9XEzoCmYvzjPh7jrFWkbpOSHGI71ve3dkSvBy5tyiSL3TtivfKsIC+9ZxuEJZ3d3lIjc9e+yz4HVbqQ==
|
||||
dependencies:
|
||||
"@stdlib/assert" "^0.0.x"
|
||||
"@stdlib/cli" "^0.0.x"
|
||||
"@stdlib/fs" "^0.0.x"
|
||||
"@stdlib/process" "^0.0.x"
|
||||
"@stdlib/utils" "^0.0.x"
|
||||
|
||||
"@stdlib/process@^0.0.x":
|
||||
version "0.0.12"
|
||||
resolved "https://registry.yarnpkg.com/@stdlib/process/-/process-0.0.12.tgz#123325079d89a32f4212f72fb694f8fe3614cf18"
|
||||
integrity sha512-P0X0TMvkissBE1Wr877Avi2/AxmP7X5Toa6GatHbpJdDg6jQmN4SgPd+NZNp98YtZUyk478c8XSIzMr1krQ20g==
|
||||
dependencies:
|
||||
"@stdlib/assert" "^0.0.x"
|
||||
"@stdlib/buffer" "^0.0.x"
|
||||
"@stdlib/cli" "^0.0.x"
|
||||
"@stdlib/fs" "^0.0.x"
|
||||
"@stdlib/streams" "^0.0.x"
|
||||
"@stdlib/string" "^0.0.x"
|
||||
"@stdlib/utils" "^0.0.x"
|
||||
|
||||
"@stdlib/random@^0.0.x":
|
||||
version "0.0.12"
|
||||
resolved "https://registry.yarnpkg.com/@stdlib/random/-/random-0.0.12.tgz#e819c3abd602ed5559ba800dba751e49c633ff85"
|
||||
integrity sha512-c5yND4Ahnm9Jx0I+jsKhn4Yrz10D53ALSrIe3PG1qIz3kNFcIPnmvCuNGd+3V4ch4Mbrez55Y8z/ZC5RJh4vJQ==
|
||||
dependencies:
|
||||
"@stdlib/array" "^0.0.x"
|
||||
"@stdlib/assert" "^0.0.x"
|
||||
"@stdlib/blas" "^0.0.x"
|
||||
"@stdlib/buffer" "^0.0.x"
|
||||
"@stdlib/cli" "^0.0.x"
|
||||
"@stdlib/constants" "^0.0.x"
|
||||
"@stdlib/fs" "^0.0.x"
|
||||
"@stdlib/math" "^0.0.x"
|
||||
"@stdlib/process" "^0.0.x"
|
||||
"@stdlib/stats" "^0.0.x"
|
||||
"@stdlib/streams" "^0.0.x"
|
||||
"@stdlib/symbol" "^0.0.x"
|
||||
"@stdlib/types" "^0.0.x"
|
||||
"@stdlib/utils" "^0.0.x"
|
||||
debug "^2.6.9"
|
||||
readable-stream "^2.1.4"
|
||||
|
||||
"@stdlib/regexp@^0.0.x":
|
||||
version "0.0.13"
|
||||
resolved "https://registry.yarnpkg.com/@stdlib/regexp/-/regexp-0.0.13.tgz#80b98361dc7a441b47bc3fa964bb0c826759e971"
|
||||
integrity sha512-3JT5ZIoq/1nXY+dY+QtkU8/m7oWDeekyItEEXMx9c/AOf0ph8fmvTUGMDNfUq0RetcznFe3b66kFz6Zt4XHviA==
|
||||
dependencies:
|
||||
"@stdlib/assert" "^0.0.x"
|
||||
"@stdlib/utils" "^0.0.x"
|
||||
|
||||
"@stdlib/stats@^0.0.13", "@stdlib/stats@^0.0.x":
|
||||
version "0.0.13"
|
||||
resolved "https://registry.yarnpkg.com/@stdlib/stats/-/stats-0.0.13.tgz#87c973f385379d794707c7b5196a173dba8b07e1"
|
||||
integrity sha512-hm+t32dKbx/L7+7WlQ1o4NDEzV0J4QSnwFBCsIMIAO8+VPxTZ4FxyNERl4oKlS3hZZe4AVKjoOVhBDtgEWrS4g==
|
||||
dependencies:
|
||||
"@stdlib/array" "^0.0.x"
|
||||
"@stdlib/assert" "^0.0.x"
|
||||
"@stdlib/blas" "^0.0.x"
|
||||
"@stdlib/constants" "^0.0.x"
|
||||
"@stdlib/math" "^0.0.x"
|
||||
"@stdlib/ndarray" "^0.0.x"
|
||||
"@stdlib/random" "^0.0.x"
|
||||
"@stdlib/string" "^0.0.x"
|
||||
"@stdlib/symbol" "^0.0.x"
|
||||
"@stdlib/types" "^0.0.x"
|
||||
"@stdlib/utils" "^0.0.x"
|
||||
|
||||
"@stdlib/streams@^0.0.x":
|
||||
version "0.0.12"
|
||||
resolved "https://registry.yarnpkg.com/@stdlib/streams/-/streams-0.0.12.tgz#07f5ceae5852590afad8e1cb7ce94174becc8739"
|
||||
integrity sha512-YLUlXwjJNknHp92IkJUdvn5jEQjDckpawKhDLLCoxyh3h5V+w/8+61SH7TMTfKx5lBxKJ8vvtchZh90mIJOAjQ==
|
||||
dependencies:
|
||||
"@stdlib/assert" "^0.0.x"
|
||||
"@stdlib/buffer" "^0.0.x"
|
||||
"@stdlib/cli" "^0.0.x"
|
||||
"@stdlib/fs" "^0.0.x"
|
||||
"@stdlib/types" "^0.0.x"
|
||||
"@stdlib/utils" "^0.0.x"
|
||||
debug "^2.6.9"
|
||||
readable-stream "^2.1.4"
|
||||
|
||||
"@stdlib/strided@^0.0.x":
|
||||
version "0.0.12"
|
||||
resolved "https://registry.yarnpkg.com/@stdlib/strided/-/strided-0.0.12.tgz#86ac48e660cb7f64a45cf07e80cbbfe58be21ae1"
|
||||
integrity sha512-1NINP+Y7IJht34iri/bYLY7TVxrip51f6Z3qWxGHUCH33kvk5H5QqV+RsmFEGbbyoGtdeHrT2O+xA+7R2e3SNg==
|
||||
dependencies:
|
||||
"@stdlib/assert" "^0.0.x"
|
||||
"@stdlib/math" "^0.0.x"
|
||||
"@stdlib/ndarray" "^0.0.x"
|
||||
"@stdlib/types" "^0.0.x"
|
||||
"@stdlib/utils" "^0.0.x"
|
||||
|
||||
"@stdlib/string@^0.0.x":
|
||||
version "0.0.13"
|
||||
resolved "https://registry.yarnpkg.com/@stdlib/string/-/string-0.0.13.tgz#37457ca49e8d1dff0e523c68f5673c655c79eb2d"
|
||||
integrity sha512-nGMHi7Qk9LBW0+Y+e3pSePQEBqyWH7+7DjFR1APcbsYccJE0p4aCaQdhPhx9Tp7j3uRGBmqPFek8wpcvIuC+CQ==
|
||||
dependencies:
|
||||
"@stdlib/assert" "^0.0.x"
|
||||
"@stdlib/cli" "^0.0.x"
|
||||
"@stdlib/constants" "^0.0.x"
|
||||
"@stdlib/fs" "^0.0.x"
|
||||
"@stdlib/math" "^0.0.x"
|
||||
"@stdlib/nlp" "^0.0.x"
|
||||
"@stdlib/process" "^0.0.x"
|
||||
"@stdlib/regexp" "^0.0.x"
|
||||
"@stdlib/streams" "^0.0.x"
|
||||
"@stdlib/types" "^0.0.x"
|
||||
"@stdlib/utils" "^0.0.x"
|
||||
|
||||
"@stdlib/symbol@^0.0.x":
|
||||
version "0.0.12"
|
||||
resolved "https://registry.yarnpkg.com/@stdlib/symbol/-/symbol-0.0.12.tgz#b9f396b0bf269c2985bb7fe99810a8e26d7288c3"
|
||||
integrity sha512-2IDhpzWVGeLHgsvIsX12RXvf78r7xBkc4QLoRUv3k7Cp61BisR1Ym1p0Tq9PbxT8fknlvLToh9n5RpmESi2d4w==
|
||||
dependencies:
|
||||
"@stdlib/assert" "^0.0.x"
|
||||
"@stdlib/utils" "^0.0.x"
|
||||
|
||||
"@stdlib/time@^0.0.x":
|
||||
version "0.0.14"
|
||||
resolved "https://registry.yarnpkg.com/@stdlib/time/-/time-0.0.14.tgz#ea6daa438b1d3b019b99f5091117ee4bcef55d60"
|
||||
integrity sha512-1gMFCQTabMVIgww+k4g8HHHIhyy1tIlvwT8mC0BHW7Q7TzDAgobwL0bvor+lwvCb5LlDAvNQEpaRgVT99QWGeQ==
|
||||
dependencies:
|
||||
"@stdlib/assert" "^0.0.x"
|
||||
"@stdlib/cli" "^0.0.x"
|
||||
"@stdlib/constants" "^0.0.x"
|
||||
"@stdlib/fs" "^0.0.x"
|
||||
"@stdlib/math" "^0.0.x"
|
||||
"@stdlib/string" "^0.0.x"
|
||||
"@stdlib/utils" "^0.0.x"
|
||||
|
||||
"@stdlib/types@^0.0.x":
|
||||
version "0.0.14"
|
||||
resolved "https://registry.yarnpkg.com/@stdlib/types/-/types-0.0.14.tgz#02d3aab7a9bfaeb86e34ab749772ea22f7b2f7e0"
|
||||
integrity sha512-AP3EI9/il/xkwUazcoY+SbjtxHRrheXgSbWZdEGD+rWpEgj6n2i63hp6hTOpAB5NipE0tJwinQlDGOuQ1lCaCw==
|
||||
|
||||
"@stdlib/utils@^0.0.x":
|
||||
version "0.0.12"
|
||||
resolved "https://registry.yarnpkg.com/@stdlib/utils/-/utils-0.0.12.tgz#670de5a7b253f04f11a4cba38f790e82393bcb46"
|
||||
integrity sha512-+JhFpl6l7RSq/xGnbWRQ5dAL90h9ONj8MViqlb7teBZFtePZLMwoRA1wssypFcJ8SFMRWQn7lPmpYVUkGwRSOg==
|
||||
dependencies:
|
||||
"@stdlib/array" "^0.0.x"
|
||||
"@stdlib/assert" "^0.0.x"
|
||||
"@stdlib/blas" "^0.0.x"
|
||||
"@stdlib/buffer" "^0.0.x"
|
||||
"@stdlib/cli" "^0.0.x"
|
||||
"@stdlib/constants" "^0.0.x"
|
||||
"@stdlib/fs" "^0.0.x"
|
||||
"@stdlib/math" "^0.0.x"
|
||||
"@stdlib/os" "^0.0.x"
|
||||
"@stdlib/process" "^0.0.x"
|
||||
"@stdlib/random" "^0.0.x"
|
||||
"@stdlib/regexp" "^0.0.x"
|
||||
"@stdlib/streams" "^0.0.x"
|
||||
"@stdlib/string" "^0.0.x"
|
||||
"@stdlib/symbol" "^0.0.x"
|
||||
"@stdlib/time" "^0.0.x"
|
||||
"@stdlib/types" "^0.0.x"
|
||||
debug "^2.6.9"
|
||||
|
||||
complex.js@^2.1.1:
|
||||
version "2.1.1"
|
||||
resolved "https://registry.yarnpkg.com/complex.js/-/complex.js-2.1.1.tgz#0675dac8e464ec431fb2ab7d30f41d889fb25c31"
|
||||
integrity sha512-8njCHOTtFFLtegk6zQo0kkVX1rngygb/KQI6z1qZxlFI3scluC+LVTCFbrkWjBv4vvLlbQ9t88IPMC6k95VTTg==
|
||||
|
||||
core-util-is@~1.0.0:
|
||||
version "1.0.3"
|
||||
resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.3.tgz#a6042d3634c2b27e9328f837b965fac83808db85"
|
||||
integrity sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==
|
||||
|
||||
debug@^2.6.9:
|
||||
version "2.6.9"
|
||||
resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f"
|
||||
integrity sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==
|
||||
dependencies:
|
||||
ms "2.0.0"
|
||||
|
||||
decimal.js@^10.3.1:
|
||||
version "10.3.1"
|
||||
resolved "https://registry.yarnpkg.com/decimal.js/-/decimal.js-10.3.1.tgz#d8c3a444a9c6774ba60ca6ad7261c3a94fd5e783"
|
||||
integrity sha512-V0pfhfr8suzyPGOx3nmq4aHqabehUZn6Ch9kyFpV79TGDTWFmHqUqXdabR7QHqxzrYolF4+tVmJhUG4OURg5dQ==
|
||||
|
||||
escape-latex@^1.2.0:
|
||||
version "1.2.0"
|
||||
resolved "https://registry.yarnpkg.com/escape-latex/-/escape-latex-1.2.0.tgz#07c03818cf7dac250cce517f4fda1b001ef2bca1"
|
||||
integrity sha512-nV5aVWW1K0wEiUIEdZ4erkGGH8mDxGyxSeqPzRNtWP7ataw+/olFObw7hujFWlVjNsaDFw5VZ5NzVSIqRgfTiw==
|
||||
|
||||
fraction.js@^4.2.0:
|
||||
version "4.2.0"
|
||||
resolved "https://registry.yarnpkg.com/fraction.js/-/fraction.js-4.2.0.tgz#448e5109a313a3527f5a3ab2119ec4cf0e0e2950"
|
||||
integrity sha512-MhLuK+2gUcnZe8ZHlaaINnQLl0xRIGRfcGk2yl8xoQAfHrSsL3rYu6FCmBdkdbhc9EPlwyGHewaRsvwRMJtAlA==
|
||||
|
||||
inherits@~2.0.3:
|
||||
version "2.0.4"
|
||||
resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c"
|
||||
integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==
|
||||
|
||||
isarray@~1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11"
|
||||
integrity sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==
|
||||
|
||||
javascript-natural-sort@^0.7.1:
|
||||
version "0.7.1"
|
||||
resolved "https://registry.yarnpkg.com/javascript-natural-sort/-/javascript-natural-sort-0.7.1.tgz#f9e2303d4507f6d74355a73664d1440fb5a0ef59"
|
||||
integrity sha512-nO6jcEfZWQXDhOiBtG2KvKyEptz7RVbpGP4vTD2hLBdmNQSsCiicO2Ioinv6UI4y9ukqnBpy+XZ9H6uLNgJTlw==
|
||||
|
||||
jstat@^1.9.5:
|
||||
version "1.9.5"
|
||||
resolved "https://registry.yarnpkg.com/jstat/-/jstat-1.9.5.tgz#9941741566f683624ddeb56f5ba60ed8c29b374e"
|
||||
integrity sha512-cWnp4vObF5GmB2XsIEzxI/1ZTcYlcfNqxQ/9Fp5KFUa0Jf/4tO0ZkGVnqoEHDisJvYgvn5n3eWZbd2xTVJJPUQ==
|
||||
|
||||
lodash@^4.17.21:
|
||||
version "4.17.21"
|
||||
resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c"
|
||||
integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==
|
||||
|
||||
mathjs@^10.6.0:
|
||||
version "10.6.1"
|
||||
resolved "https://registry.yarnpkg.com/mathjs/-/mathjs-10.6.1.tgz#95b34178eed65cbf7a63d35c468ad3ac912f7ddf"
|
||||
integrity sha512-8iZp6uUKKBoCFoUHze9ydsrSji9/IOEzMhwURyoQXaLL1+ILEZnraw4KzZnUBt/XN6lPJPV+7JO94oil3AmosQ==
|
||||
dependencies:
|
||||
"@babel/runtime" "^7.18.3"
|
||||
complex.js "^2.1.1"
|
||||
decimal.js "^10.3.1"
|
||||
escape-latex "^1.2.0"
|
||||
fraction.js "^4.2.0"
|
||||
javascript-natural-sort "^0.7.1"
|
||||
seedrandom "^3.0.5"
|
||||
tiny-emitter "^2.1.0"
|
||||
typed-function "^2.1.0"
|
||||
|
||||
minimist@^1.2.0:
|
||||
version "1.2.6"
|
||||
resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.6.tgz#8637a5b759ea0d6e98702cfb3a9283323c93af44"
|
||||
integrity sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==
|
||||
|
||||
ms@2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8"
|
||||
integrity sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==
|
||||
|
||||
pdfast@^0.2.0:
|
||||
version "0.2.0"
|
||||
resolved "https://registry.yarnpkg.com/pdfast/-/pdfast-0.2.0.tgz#8cbc556e1bf2522177787c0de2e0d4373ba885c9"
|
||||
integrity sha512-cq6TTu6qKSFUHwEahi68k/kqN2mfepjkGrG9Un70cgdRRKLKY6Rf8P8uvP2NvZktaQZNF3YE7agEkLj0vGK9bA==
|
||||
|
||||
process-nextick-args@~2.0.0:
|
||||
version "2.0.1"
|
||||
resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.1.tgz#7820d9b16120cc55ca9ae7792680ae7dba6d7fe2"
|
||||
integrity sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==
|
||||
|
||||
readable-stream@^2.1.4:
|
||||
version "2.3.7"
|
||||
resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.7.tgz#1eca1cf711aef814c04f62252a36a62f6cb23b57"
|
||||
integrity sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==
|
||||
dependencies:
|
||||
core-util-is "~1.0.0"
|
||||
inherits "~2.0.3"
|
||||
isarray "~1.0.0"
|
||||
process-nextick-args "~2.0.0"
|
||||
safe-buffer "~5.1.1"
|
||||
string_decoder "~1.1.1"
|
||||
util-deprecate "~1.0.1"
|
||||
|
||||
regenerator-runtime@^0.13.4:
|
||||
version "0.13.9"
|
||||
resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.13.9.tgz#8925742a98ffd90814988d7566ad30ca3b263b52"
|
||||
integrity sha512-p3VT+cOEgxFsRRA9X4lkI1E+k2/CtnKtU4gcxyaCUreilL/vqI6CdZ3wxVUx3UOUg+gnUOQQcRI7BmSI656MYA==
|
||||
|
||||
rescript@^9.1.4:
|
||||
version "9.1.4"
|
||||
resolved "https://registry.yarnpkg.com/rescript/-/rescript-9.1.4.tgz#1eb126f98d6c16942c0bf0df67c050198e580515"
|
||||
integrity sha512-aXANK4IqecJzdnDpJUsU6pxMViCR5ogAxzuqS0mOr8TloMnzAjJFu63fjD6LCkWrKAhlMkFFzQvVQYaAaVkFXw==
|
||||
|
||||
safe-buffer@~5.1.0, safe-buffer@~5.1.1:
|
||||
version "5.1.2"
|
||||
resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d"
|
||||
integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==
|
||||
|
||||
seedrandom@^3.0.5:
|
||||
version "3.0.5"
|
||||
resolved "https://registry.yarnpkg.com/seedrandom/-/seedrandom-3.0.5.tgz#54edc85c95222525b0c7a6f6b3543d8e0b3aa0a7"
|
||||
integrity sha512-8OwmbklUNzwezjGInmZ+2clQmExQPvomqjL7LFqOYqtmuxRgQYqOD3mHaU+MvZn5FLUeVxVfQjwLZW/n/JFuqg==
|
||||
|
||||
string_decoder@~1.1.1:
|
||||
version "1.1.1"
|
||||
resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.1.1.tgz#9cf1611ba62685d7030ae9e4ba34149c3af03fc8"
|
||||
integrity sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==
|
||||
dependencies:
|
||||
safe-buffer "~5.1.0"
|
||||
|
||||
tiny-emitter@^2.1.0:
|
||||
version "2.1.0"
|
||||
resolved "https://registry.yarnpkg.com/tiny-emitter/-/tiny-emitter-2.1.0.tgz#1d1a56edfc51c43e863cbb5382a72330e3555423"
|
||||
integrity sha512-NB6Dk1A9xgQPMoGqC5CVXn123gWyte215ONT5Pp5a0yt4nlEoO1ZWeCwpncaekPHXO60i47ihFnZPiRPjRMq4Q==
|
||||
|
||||
typed-function@^2.1.0:
|
||||
version "2.1.0"
|
||||
resolved "https://registry.yarnpkg.com/typed-function/-/typed-function-2.1.0.tgz#ded6f8a442ba8749ff3fe75bc41419c8d46ccc3f"
|
||||
integrity sha512-bctQIOqx2iVbWGDGPWwIm18QScpu2XRmkC19D8rQGFsjKSgteq/o1hTZvIG/wuDq8fanpBDrLkLq+aEN/6y5XQ==
|
||||
|
||||
util-deprecate@~1.0.1:
|
||||
version "1.0.2"
|
||||
resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf"
|
||||
integrity sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==
|
||||
|
||||
utility-tools@^0.2.2:
|
||||
version "0.2.2"
|
||||
resolved "https://registry.yarnpkg.com/utility-tools/-/utility-tools-0.2.2.tgz#fdea9678d4d3b6e8b76184b35e6ac97e20c6079d"
|
||||
integrity sha512-Bbp5jZaxPSeALD75A2AGh0rvmuYSXBqZ3h6W5+VJIoRympXYwAJ3k8UmBNCBuM0uLu6XdSeYIfR4sRlgg+jrIA==
|
||||
dependencies:
|
||||
"@quri/squiggle-lang" "^0.2.11"
|
|
@ -1 +0,0 @@
|
|||
Deprecated; see webpage-refactor instead.
|
|
@ -1,601 +0,0 @@
|
|||
/* Imports */
|
||||
import Head from "next/head";
|
||||
import React, { useState } from "react";
|
||||
import { DrawGraph, removeOldSvg } from "./labeledGraph";
|
||||
import { SubmitButton } from "./submitButton";
|
||||
import { DisplayElement } from "./displayElement";
|
||||
import { DisplayAsMarkdown } from "./displayAsMarkdown";
|
||||
import { CreateTable, buildRows } from "./findPaths";
|
||||
import { DataSetChanger } from "./datasetChanger";
|
||||
import { ComparisonsChanger } from "./comparisonsChanger";
|
||||
import { pushToMongo } from "./pushToMongo.js";
|
||||
import {
|
||||
increasingList,
|
||||
maxMergeSortSteps,
|
||||
expectedNumMergeSortSteps,
|
||||
conservativeNumMergeSortSteps,
|
||||
} from "./utils.js";
|
||||
|
||||
/* DEFINTIONS */
|
||||
const DEFAULT_COMPARE = () => "x to y"; // 1/Math.random() - 1 // Useful for testing, cause I can make the default number change.
|
||||
const estimatedMergeSortSteps = conservativeNumMergeSortSteps; // pander to human biases so that users complain less.
|
||||
|
||||
/* Misc. helpers */
|
||||
let buildLinks = (quantitativeComparisons) =>
|
||||
quantitativeComparisons.map(
|
||||
([element1, element2, distance, reasoning, squiggleString]) => ({
|
||||
source: element1,
|
||||
target: element2,
|
||||
distance: distance,
|
||||
reasoning: reasoning,
|
||||
squiggleString: squiggleString,
|
||||
})
|
||||
);
|
||||
|
||||
Array.prototype.containsArray = function (val) {
|
||||
var hash = {};
|
||||
for (var i = 0; i < this.length; i++) {
|
||||
hash[this[i]] = i;
|
||||
}
|
||||
return hash.hasOwnProperty(val);
|
||||
};
|
||||
|
||||
let checkIfListIsOrdered = (arr, binaryComparisons) => {
|
||||
let l = arr.length;
|
||||
let isOrdered = true;
|
||||
for (let i = 0; i < l - 1; i++) {
|
||||
isOrdered =
|
||||
isOrdered && binaryComparisons.containsArray([arr[i], arr[i + 1]]);
|
||||
}
|
||||
return isOrdered;
|
||||
};
|
||||
|
||||
let nicelyFormatLinks = (quantitativeComparisons, listOfElements) =>
|
||||
quantitativeComparisons.map(
|
||||
([element1, element2, distance, reasoning, squiggleString]) => ({
|
||||
source: listOfElements[element1].name,
|
||||
target: listOfElements[element2].name,
|
||||
distance: distance,
|
||||
reasoning: reasoning,
|
||||
squiggleString: squiggleString,
|
||||
})
|
||||
);
|
||||
|
||||
// Main react component
|
||||
export default function ComparisonView({ listOfElementsForView }) {
|
||||
/* State */
|
||||
// initial state values
|
||||
let initialListOfElements = listOfElementsForView.map((element, i) => ({
|
||||
...element,
|
||||
id: i,
|
||||
}));
|
||||
let initialPosList = increasingList(listOfElementsForView.length); // [0,1,2,3,4]
|
||||
let initialComparePair = [
|
||||
initialPosList[initialPosList.length - 2],
|
||||
initialPosList[initialPosList.length - 1],
|
||||
];
|
||||
let initialInputValue = "x to y";
|
||||
let initialReasoning = "";
|
||||
let initialBinaryComparisons = [];
|
||||
let initialQuantitativeComparisons = [];
|
||||
let initialIsListOdered = false;
|
||||
let initialOrderedList = [];
|
||||
let initialShowAdvancedOptions = false;
|
||||
let initialShowComparisons = false;
|
||||
let initialShowLoadComparisons = false;
|
||||
let initialShowChangeDataSet = false;
|
||||
let initialNumSteps = 0;
|
||||
let initialMaxSteps = maxMergeSortSteps(listOfElementsForView.length);
|
||||
let initialExpectedSteps = estimatedMergeSortSteps(
|
||||
listOfElementsForView.length
|
||||
);
|
||||
let initialTableRows = [];
|
||||
let initialDontPushSubmitButtonAnyMore = false;
|
||||
|
||||
// state variables and functions
|
||||
const [listOfElements, setListOfElements] = useState(initialListOfElements);
|
||||
const [posList, setPosList] = useState(initialPosList);
|
||||
const [toComparePair, setToComparePair] = useState(initialComparePair);
|
||||
const [inputValue, setInputValue] = useState(initialInputValue);
|
||||
const [reasoning, setReasoning] = useState(initialReasoning);
|
||||
const [binaryComparisons, setBinaryComparisons] = useState(
|
||||
initialBinaryComparisons
|
||||
);
|
||||
const [quantitativeComparisons, setQuantitativeComparisons] = useState(
|
||||
initialQuantitativeComparisons
|
||||
); // More expressive, but more laborious to search through. For the ordering step, I only manipulate the binaryComparisons.
|
||||
|
||||
const [isListOrdered, setIsListOrdered] = useState(initialIsListOdered);
|
||||
const [orderedList, setOrderedList] = useState(initialOrderedList);
|
||||
const [dontPushSubmitButtonAnyMore, setDontPushSubmitButtonAnyMore] =
|
||||
useState(initialDontPushSubmitButtonAnyMore);
|
||||
|
||||
let [showAdvancedOptions, changeShowAdvanceOptions] = useState(
|
||||
initialShowAdvancedOptions
|
||||
);
|
||||
let [showComparisons, changeShowComparisons] = useState(
|
||||
initialShowComparisons
|
||||
);
|
||||
let [showLoadComparisons, changeShowLoadComparisons] = useState(
|
||||
initialShowLoadComparisons
|
||||
);
|
||||
let [showChangeDataSet, changeshowChangeDataSet] = useState(
|
||||
initialShowChangeDataSet
|
||||
);
|
||||
let [numSteps, changeNumSteps] = useState(initialNumSteps);
|
||||
let [maxSteps, changeMaxSteps] = useState(initialMaxSteps);
|
||||
let [expectedSteps, changeExpectedSteps] = useState(initialExpectedSteps);
|
||||
let [tableRows, setTableRows] = useState(initialTableRows);
|
||||
|
||||
/* Convenience utils: restart + changeDataSet */
|
||||
let restart = (
|
||||
posList,
|
||||
initialBinaryComparisons2,
|
||||
initialQuantitativeComparisons2
|
||||
) => {
|
||||
//({posList, initialBinaryComparisons2, initialQuantitativeComparisons2}) => {
|
||||
setToComparePair([
|
||||
posList[posList.length - 2],
|
||||
posList[posList.length - 1],
|
||||
]);
|
||||
setInputValue(initialInputValue);
|
||||
setBinaryComparisons(initialBinaryComparisons2 || initialBinaryComparisons);
|
||||
setQuantitativeComparisons(
|
||||
initialQuantitativeComparisons2 || initialQuantitativeComparisons
|
||||
);
|
||||
setIsListOrdered(initialIsListOdered);
|
||||
setOrderedList(initialOrderedList);
|
||||
changeNumSteps(initialNumSteps);
|
||||
removeOldSvg();
|
||||
setTableRows(initialTableRows);
|
||||
setDontPushSubmitButtonAnyMore(initialDontPushSubmitButtonAnyMore);
|
||||
};
|
||||
|
||||
let changeDataSet = (listOfElementsNew) => {
|
||||
listOfElementsNew = listOfElementsNew.map((element, i) => ({
|
||||
...element,
|
||||
id: i,
|
||||
}));
|
||||
let newPosList = increasingList(listOfElementsNew.length);
|
||||
let newListLength = listOfElementsNew.length;
|
||||
|
||||
setListOfElements(listOfElementsNew);
|
||||
setPosList(increasingList(listOfElementsNew.length));
|
||||
setToComparePair([
|
||||
newPosList[newPosList.length - 2],
|
||||
newPosList[newPosList.length - 1],
|
||||
]);
|
||||
|
||||
changeExpectedSteps(estimatedMergeSortSteps(newListLength));
|
||||
changeMaxSteps(maxMergeSortSteps(newListLength));
|
||||
|
||||
restart(newPosList);
|
||||
// restart({posList: newPosList})
|
||||
};
|
||||
|
||||
let changeComparisons = async (links) => {
|
||||
let quantitativeComparisons2 = [];
|
||||
let binaryComparisons2 = [];
|
||||
// links.shift();
|
||||
for (let link of links) {
|
||||
let { source, target, distance, reasoning, squiggleString } = link;
|
||||
let searchByName = (name, candidate) => candidate.name == name;
|
||||
let testForSource = (candidate) => searchByName(source, candidate);
|
||||
let testForTarget = (candidate) => searchByName(target, candidate);
|
||||
let element1 = listOfElements.findIndex(testForSource);
|
||||
let element2 = listOfElements.findIndex(testForTarget);
|
||||
if (element1 == -1 || element2 == -1) {
|
||||
console.log("link", link);
|
||||
console.log(source);
|
||||
console.log(target);
|
||||
alert(JSON.stringify(link, null, 4));
|
||||
throw new Error("Comparisons include unknown elements, please retry");
|
||||
}
|
||||
quantitativeComparisons2.push([
|
||||
element1,
|
||||
element2,
|
||||
distance,
|
||||
reasoning,
|
||||
squiggleString || distance,
|
||||
]);
|
||||
binaryComparisons2.push([element1, element2]);
|
||||
}
|
||||
// return ({quantitativeComparisons: quantitativeComparisons2, binaryComparisons: binaryComparisons2})
|
||||
//restart({posList, initialBinaryComparisons2=initialBinaryComparisons, initialQuantitativeComparisons2=initialQuantitativeComparisons})
|
||||
// restart(posList, binaryComparisons2, quantitativeComparisons2)
|
||||
setQuantitativeComparisons(quantitativeComparisons2);
|
||||
setBinaryComparisons(binaryComparisons2);
|
||||
};
|
||||
|
||||
// Manipulations
|
||||
let compareTwoElements = (newBinaryComparisons, element1, element2) => {
|
||||
let element1Greater = newBinaryComparisons.containsArray([
|
||||
element1,
|
||||
element2,
|
||||
]);
|
||||
let element2Greater = newBinaryComparisons.containsArray([
|
||||
element2,
|
||||
element1,
|
||||
]);
|
||||
if (element1Greater || element2Greater) {
|
||||
return element1Greater && !element2Greater;
|
||||
} else {
|
||||
setToComparePair([element1, element2]);
|
||||
//console.log(`No comparison found between ${element1} and ${element2}`)
|
||||
//console.log(`Comparisons:`)
|
||||
//console.log(JSON.stringify(newBinaryComparisons, null, 4));
|
||||
return "No comparison found";
|
||||
}
|
||||
};
|
||||
|
||||
function merge(newBinaryComparisons, left, right) {
|
||||
let sortedArr = []; // the sorted elements will go here
|
||||
|
||||
while (left.length && right.length) {
|
||||
// insert the biggest element to the sortedArr
|
||||
let comparison = compareTwoElements(
|
||||
newBinaryComparisons,
|
||||
left[0],
|
||||
right[0]
|
||||
);
|
||||
if (comparison == "No comparison found") {
|
||||
return "No comparison found; unable to proceed";
|
||||
} else if (comparison) {
|
||||
// left[0] > right[0]
|
||||
sortedArr.push(left.shift());
|
||||
} else {
|
||||
sortedArr.push(right.shift());
|
||||
}
|
||||
}
|
||||
|
||||
// use spread operator and create a new array, combining the three arrays
|
||||
return [...sortedArr, ...left, ...right]; // if they don't have the same size, the remaining ones will be greater than the ones before
|
||||
}
|
||||
|
||||
function mergeSort({ array, comparisons }) {
|
||||
console.log("mergesort");
|
||||
console.log({ array, comparisons });
|
||||
console.log("/console");
|
||||
if (array == "No comparison found; unable to proceed") {
|
||||
return "No comparison found; unable to proceed";
|
||||
}
|
||||
const half = array.length / 2;
|
||||
|
||||
// the base case is array length <=1
|
||||
if (array.length <= 1) {
|
||||
return array;
|
||||
}
|
||||
|
||||
const left = array.slice(0, half); // the first half of the array
|
||||
const right = array.slice(half, array.length); // Note that splice is destructive.
|
||||
let orderedFirstHalf = mergeSort({ array: left, comparisons });
|
||||
let orderedSecondHalf = mergeSort({ array: right, comparisons });
|
||||
if (
|
||||
orderedFirstHalf != "No comparison found; unable to proceed" &&
|
||||
orderedSecondHalf != "No comparison found; unable to proceed"
|
||||
) {
|
||||
let result = merge(comparisons, orderedFirstHalf, orderedSecondHalf);
|
||||
return result;
|
||||
} else {
|
||||
return "No comparison found; unable to proceed";
|
||||
}
|
||||
}
|
||||
|
||||
let nextStepSimple = (posList, binaryComparisons, element1, element2) => {
|
||||
//console.log("Binary comparisons: ")
|
||||
//console.log(JSON.stringify(binaryComparisons, null, 4));
|
||||
|
||||
let newComparison = [element1, element2]; // [element1, element2]
|
||||
let newBinaryComparisons = [...binaryComparisons, newComparison];
|
||||
//console.log("New binaryComparisons: ")
|
||||
//console.log(JSON.stringify(newBinaryComparisons, null, 4));
|
||||
setBinaryComparisons(newBinaryComparisons);
|
||||
|
||||
let result = mergeSort({
|
||||
array: posList,
|
||||
comparisons: newBinaryComparisons,
|
||||
});
|
||||
//console.log(result)
|
||||
if (
|
||||
result != "No comparison found; unable to proceed" &&
|
||||
checkIfListIsOrdered(result, newBinaryComparisons)
|
||||
) {
|
||||
// console.log(`isListOrdered: ${isListOrdered}`)
|
||||
console.log("poslist@nextStepSimple");
|
||||
console.log(posList);
|
||||
console.log("result@nextStepSimple");
|
||||
console.log(result);
|
||||
|
||||
return [true, result];
|
||||
} else {
|
||||
return [false, result];
|
||||
}
|
||||
};
|
||||
|
||||
let nextStepInput = async ({
|
||||
posList,
|
||||
binaryComparisons,
|
||||
inputValue,
|
||||
reasoning,
|
||||
element1,
|
||||
element2,
|
||||
squiggleString,
|
||||
}) => {
|
||||
if (!dontPushSubmitButtonAnyMore) {
|
||||
if (inputValue < 1 && inputValue > 0) {
|
||||
let inverse = 1 / inputValue;
|
||||
if (squiggleString == inputValue) {
|
||||
inputValue = inverse;
|
||||
squiggleString = inverse;
|
||||
} else {
|
||||
inputValue = inverse;
|
||||
squiggleString = `(${squiggleString})^(-1)`;
|
||||
}
|
||||
[element1, element2] = [element2, element1];
|
||||
}
|
||||
console.log(`posList@nextStepInput:`);
|
||||
console.log(posList);
|
||||
let [successStatus, result] = nextStepSimple(
|
||||
posList,
|
||||
binaryComparisons,
|
||||
element1,
|
||||
element2
|
||||
);
|
||||
|
||||
let newQuantitativeComparison = [
|
||||
element1,
|
||||
element2,
|
||||
inputValue,
|
||||
reasoning,
|
||||
squiggleString || inputValue,
|
||||
];
|
||||
let newQuantitativeComparisons = [
|
||||
...quantitativeComparisons,
|
||||
newQuantitativeComparison,
|
||||
];
|
||||
setQuantitativeComparisons(newQuantitativeComparisons);
|
||||
|
||||
setInputValue(DEFAULT_COMPARE());
|
||||
setReasoning("");
|
||||
changeNumSteps(numSteps + 1);
|
||||
if (successStatus) {
|
||||
setDontPushSubmitButtonAnyMore(true);
|
||||
|
||||
let jsObject = nicelyFormatLinks(
|
||||
quantitativeComparisons,
|
||||
listOfElements
|
||||
);
|
||||
await pushToMongo(jsObject);
|
||||
console.log(jsObject);
|
||||
|
||||
alert(
|
||||
"Comparisons completed. Background work might take a while, or straight-out fail"
|
||||
);
|
||||
setIsListOrdered(true);
|
||||
setOrderedList(result);
|
||||
|
||||
await buildRows({
|
||||
isListOrdered: true,
|
||||
orderedList: result,
|
||||
listOfElements,
|
||||
links: buildLinks(newQuantitativeComparisons),
|
||||
rows: tableRows,
|
||||
setTableRows,
|
||||
});
|
||||
/*
|
||||
setTimeout(async () => {
|
||||
// Make sure to do this after the
|
||||
|
||||
}, 100);
|
||||
*/
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// Html
|
||||
return (
|
||||
<div className="flex flex-col items-center justify-center min-h-screen py-2">
|
||||
{/* Webpage name & favicon */}
|
||||
<div className="mt-20">
|
||||
<Head>
|
||||
<title>Utility Function Extractor</title>
|
||||
<link rel="icon" href="/favicon.ico" />
|
||||
</Head>
|
||||
</div>
|
||||
<main className="flex flex-col items-center w-full flex-1 px-20 text-center">
|
||||
{/* Heading */}
|
||||
<h1 className="text-6xl font-bold">Utility Function Extractor</h1>
|
||||
{/* Approximate progress indicator */}
|
||||
|
||||
<p>{`${numSteps} out of ~${expectedSteps} (max ${maxSteps}) comparisons`}</p>
|
||||
|
||||
{/* Comparison section */}
|
||||
<div className={isListOrdered ? "hidden" : ""}>
|
||||
<div className="flex flex-wrap items-center max-w-4xl sm:w-full mt-10">
|
||||
{/* Element 1 */}
|
||||
<div className="flex m-auto border-gray-300 border-4 h-72 w-72 p-5">
|
||||
<div className="block m-auto text-center">
|
||||
<DisplayElement
|
||||
element={listOfElements[toComparePair[0]]}
|
||||
></DisplayElement>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Comparison actuator (text, previously number) */}
|
||||
<div className="flex m-auto w-72">
|
||||
<div className="block m-auto text-center">
|
||||
<br />
|
||||
<label>
|
||||
{`... is `}
|
||||
<br />
|
||||
<input
|
||||
type="text"
|
||||
className="text-center text-blueGray-600 bg-white rounded text-lg border-0 shadow outline-none focus:outline-none focus:ring w-8/12 h-10 m-2"
|
||||
value={inputValue}
|
||||
onChange={(event) => {
|
||||
//console.log(event)
|
||||
//console.log(event.target.value)
|
||||
setInputValue(event.target.value);
|
||||
}}
|
||||
/>
|
||||
<br />
|
||||
{`times as valuable as ...`}
|
||||
</label>
|
||||
<br />
|
||||
|
||||
<SubmitButton
|
||||
posList={posList}
|
||||
binaryComparisons={binaryComparisons}
|
||||
inputValue={inputValue}
|
||||
reasoning={reasoning}
|
||||
toComparePair={toComparePair}
|
||||
nextStepInput={nextStepInput}
|
||||
dontPushSubmitButtonAnyMore={dontPushSubmitButtonAnyMore}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Element 2 */}
|
||||
<div className="flex m-auto border-gray-300 border-4 h-72 w-72 p-5">
|
||||
<div className="block m-auto text-center">
|
||||
<DisplayElement
|
||||
element={listOfElements[toComparePair[1]]}
|
||||
></DisplayElement>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<br />
|
||||
|
||||
<label className="">
|
||||
{"Notes and reasoning:"}
|
||||
<textarea
|
||||
className="mt-2 px-3 py-4 placeholder-blueGray-300 text-blueGray-600 relative bg-white bg-white rounded text-base border-0 shadow outline-none focus:outline-none focus:ring w-full"
|
||||
placeholder={
|
||||
numSteps == 0
|
||||
? "Please write your name here if you want QURI to be able to identify your answers later"
|
||||
: ""
|
||||
}
|
||||
value={reasoning}
|
||||
onChange={(event) => setReasoning(event.target.value)}
|
||||
/>
|
||||
</label>
|
||||
<br />
|
||||
</div>
|
||||
|
||||
{/* Results section */}
|
||||
<div className={isListOrdered ? "" : "hidden"}>
|
||||
{/* Graph */}
|
||||
<div className="flex items-center text-center">
|
||||
<DrawGraph
|
||||
isListOrdered={isListOrdered}
|
||||
orderedList={orderedList}
|
||||
listOfElements={listOfElements}
|
||||
links={buildLinks(quantitativeComparisons)}
|
||||
></DrawGraph>
|
||||
</div>
|
||||
|
||||
{/* Comparison table */}
|
||||
<div className="flex items-center text-center ">
|
||||
<CreateTable
|
||||
isListOrdered={isListOrdered}
|
||||
orderedList={orderedList}
|
||||
listOfElements={listOfElements}
|
||||
links={buildLinks(quantitativeComparisons)}
|
||||
tableRows={tableRows}
|
||||
setTableRows={setTableRows}
|
||||
></CreateTable>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Convenience functions */}
|
||||
<div className="w-2/12 flex justify-center mt-10">
|
||||
<button
|
||||
className="text-gray-500 text-sm"
|
||||
onClick={() => changeShowAdvanceOptions(!showAdvancedOptions)}
|
||||
>
|
||||
Advanced options ▼
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div
|
||||
className={
|
||||
showAdvancedOptions
|
||||
? "flex flex-wrap -mx-4 overflow-hidden"
|
||||
: "hidden"
|
||||
}
|
||||
>
|
||||
{/* Button: Restart */}
|
||||
<div className="my-4 px-4 w-1/4 overflow-hidden">
|
||||
<button
|
||||
className="bg-transparent hover:bg-blue-500 text-blue-700 font-semibold hover:text-white py-2 px-4 border border-blue-500 hover:border-transparent rounded mt-5"
|
||||
onClick={() => restart(posList)}
|
||||
>
|
||||
{/* onClick={() => restart({posList})}> */}
|
||||
Restart
|
||||
</button>
|
||||
</div>
|
||||
{/* Button: Show comparisons */}
|
||||
<div className="my-4 px-4 w-1/4 overflow-hidden">
|
||||
<button
|
||||
className="bg-transparent hover:bg-blue-500 text-blue-700 font-semibold hover:text-white py-2 px-4 border border-blue-500 hover:border-transparent rounded mt-5"
|
||||
onClick={() => changeShowComparisons(!showComparisons)}
|
||||
>
|
||||
Show comparisons
|
||||
</button>
|
||||
</div>
|
||||
{/* Button: Load comparisons */}
|
||||
<div className="my-4 px-4 w-1/4 overflow-hidden">
|
||||
<button
|
||||
className="bg-transparent hover:bg-blue-500 text-blue-700 font-semibold hover:text-white py-2 px-4 border border-blue-500 hover:border-transparent rounded mt-5"
|
||||
onClick={() => changeShowLoadComparisons(!showLoadComparisons)}
|
||||
>
|
||||
Load comparisons
|
||||
</button>
|
||||
</div>
|
||||
{/* Button: Change dataset */}
|
||||
<div className="my-4 px-4 w-1/4 overflow-hidden">
|
||||
<button
|
||||
className="bg-transparent hover:bg-blue-500 text-blue-700 font-semibold hover:text-white py-2 px-4 border border-blue-500 hover:border-transparent rounded mt-5"
|
||||
onClick={() => changeshowChangeDataSet(!showChangeDataSet)}
|
||||
>
|
||||
Use your own data
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
{/* Change dataset section */}
|
||||
<div className={showChangeDataSet ? "inline mt-5" : "hidden"}>
|
||||
<DataSetChanger handleSubmit={changeDataSet} />
|
||||
</div>
|
||||
|
||||
{/* Show comparisons section */}
|
||||
<div className={showComparisons ? "inline mt-5" : "hidden"}>
|
||||
<div className="text-left">
|
||||
<DisplayAsMarkdown
|
||||
markdowntext={`
|
||||
${
|
||||
"" /*
|
||||
## Comparisons
|
||||
### Binary comparisons
|
||||
${JSON.stringify(binaryComparisons, null, 4)}
|
||||
*/
|
||||
}
|
||||
### Numerical comparisons
|
||||
${JSON.stringify(
|
||||
nicelyFormatLinks(quantitativeComparisons, listOfElements),
|
||||
null,
|
||||
4
|
||||
)}
|
||||
`}
|
||||
className={""}
|
||||
></DisplayAsMarkdown>
|
||||
</div>
|
||||
</div>
|
||||
{/* Load comparisons section */}
|
||||
<div className={showLoadComparisons ? "inline mt-5" : "hidden"}>
|
||||
<ComparisonsChanger handleSubmit={changeComparisons} />
|
||||
{/*<ComparisonsChanger handleSubmit={changeComparisons} />*/}
|
||||
</div>
|
||||
</main>
|
||||
</div>
|
||||
);
|
||||
}
|
|
@ -1,99 +0,0 @@
|
|||
import React, { useState } from "react";
|
||||
|
||||
export function ComparisonsChanger({ handleSubmit }) {
|
||||
// let defaultText=JSON.stringify(nicelyFormatLinks(quantitativeComparisons, listOfElements), null, 4)
|
||||
|
||||
let [value, setValue] = useState(``);
|
||||
const [displayingDoneMessage, setDisplayingDoneMessage] = useState(false);
|
||||
const [displayingDoneMessageTimer, setDisplayingDoneMessageTimer] =
|
||||
useState(null);
|
||||
|
||||
let handleChange = (event) => {
|
||||
setValue(event.target.value);
|
||||
};
|
||||
|
||||
let handleSubmitInner = (event) => {
|
||||
clearTimeout(displayingDoneMessageTimer);
|
||||
event.preventDefault();
|
||||
//console.log(event)
|
||||
console.log("value@handleSubmitInner@ComparisonsChanger");
|
||||
//console.log(typeof(value));
|
||||
console.log(value);
|
||||
try {
|
||||
let newData = JSON.parse(value);
|
||||
//console.log(typeof(newData))
|
||||
//console.log(newData)
|
||||
handleSubmit(newData);
|
||||
/*
|
||||
if(!newData.length || newData.length < 2){
|
||||
throw Error("Not enough objects")
|
||||
}
|
||||
*/
|
||||
setDisplayingDoneMessage(true);
|
||||
let timer = setTimeout(() => setDisplayingDoneMessage(false), 3000);
|
||||
setDisplayingDoneMessageTimer(timer);
|
||||
} catch (error) {
|
||||
setDisplayingDoneMessage(false);
|
||||
//alert(error)
|
||||
//console.log(error)
|
||||
let substituteText = `Error: ${error.message}
|
||||
|
||||
Try something like:
|
||||
[
|
||||
{
|
||||
"source": "x",
|
||||
"target": "y",
|
||||
"distance": 99999.99999999999,
|
||||
"reasoning": "blah blah"
|
||||
},
|
||||
{
|
||||
"source": "y",
|
||||
"target": "z",
|
||||
"distance": 1,
|
||||
"reasoning": "blah blah"
|
||||
},
|
||||
{
|
||||
"source": "x",
|
||||
"target": "z",
|
||||
"distance": 10,
|
||||
"reasoning": "blah blah"
|
||||
}
|
||||
]
|
||||
|
||||
Your old input was: ${value}`;
|
||||
setValue(substituteText);
|
||||
}
|
||||
};
|
||||
return (
|
||||
<form onSubmit={handleSubmitInner} className="inline">
|
||||
<p>Load comparisons in the same style as in "Show comparisons".</p>
|
||||
<p>These will override your current comparisons.</p>
|
||||
<br />
|
||||
<textarea
|
||||
value={value}
|
||||
onChange={handleChange}
|
||||
rows="10"
|
||||
cols="50"
|
||||
className=""
|
||||
/>
|
||||
<br />
|
||||
<button
|
||||
className="bg-transparent hover:bg-blue-500 text-blue-700 font-semibold hover:text-white py-2 px-4 border border-blue-500 hover:border-transparent rounded mt-5 p-10"
|
||||
onClick={handleSubmitInner}
|
||||
>
|
||||
Change comparisons
|
||||
</button>
|
||||
|
||||
<button
|
||||
className={
|
||||
displayingDoneMessage
|
||||
? "bg-transparent text-blue-700 font-semibold py-2 px-4 border border-blue-500 rounded mt-5 p-10"
|
||||
: "hidden"
|
||||
}
|
||||
>
|
||||
Done!
|
||||
</button>
|
||||
</form>
|
||||
);
|
||||
}
|
||||
|
280
packages/webpage-legacy/lib/d3experiment.js
vendored
|
@ -1,280 +0,0 @@
|
|||
import React, { useState, useEffect } from "react";
|
||||
import * as d3 from "d3";
|
||||
|
||||
export function drawChart(height, width) {
|
||||
d3.select("#chart")
|
||||
.append("svg")
|
||||
.attr("width", width)
|
||||
.attr("height", height)
|
||||
.style("border", "1px solid black")
|
||||
.append("text")
|
||||
.attr("fill", "green")
|
||||
.attr("x", 50)
|
||||
.attr("y", 50)
|
||||
.text("Hello D3");
|
||||
}
|
||||
|
||||
export function drawCircles() {
|
||||
var svg = d3
|
||||
.select("#circles")
|
||||
.append("svg")
|
||||
.attr("width", 960)
|
||||
.attr("height", 500)
|
||||
.attr("bgcolor", "blue");
|
||||
|
||||
var background = svg
|
||||
.append("rect")
|
||||
.attr("width", "100%")
|
||||
.attr("height", "100%")
|
||||
.attr("fill", "blue");
|
||||
|
||||
var ball = svg
|
||||
.append("circle")
|
||||
.attr("r", 73)
|
||||
.attr("cx", 480)
|
||||
.attr("cy", 250)
|
||||
.style("fill", "#ffe41e");
|
||||
}
|
||||
|
||||
export function drawGraph() {
|
||||
let margin = { top: 20, right: 30, bottom: 20, left: 30 };
|
||||
let width = 900 - margin.left - margin.right;
|
||||
let height = 600 - margin.top - margin.bottom;
|
||||
|
||||
var svg = d3
|
||||
.select("#graph")
|
||||
.append("svg")
|
||||
.attr("width", width + margin.left + margin.right)
|
||||
.attr("height", height + margin.top + margin.bottom)
|
||||
.append("g")
|
||||
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
|
||||
|
||||
let data = {
|
||||
nodes: [
|
||||
{
|
||||
id: 1,
|
||||
name: "A",
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
name: "B",
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
name: "C",
|
||||
},
|
||||
{
|
||||
id: 4,
|
||||
name: "D",
|
||||
},
|
||||
{
|
||||
id: 5,
|
||||
name: "E",
|
||||
},
|
||||
{
|
||||
id: 6,
|
||||
name: "F",
|
||||
},
|
||||
{
|
||||
id: 7,
|
||||
name: "G",
|
||||
},
|
||||
{
|
||||
id: 8,
|
||||
name: "H",
|
||||
},
|
||||
{
|
||||
id: 9,
|
||||
name: "I",
|
||||
},
|
||||
{
|
||||
id: 10,
|
||||
name: "J",
|
||||
},
|
||||
],
|
||||
links: [
|
||||
{
|
||||
source: 1,
|
||||
target: 2,
|
||||
},
|
||||
{
|
||||
source: 1,
|
||||
target: 5,
|
||||
},
|
||||
{
|
||||
source: 1,
|
||||
target: 6,
|
||||
},
|
||||
|
||||
{
|
||||
source: 2,
|
||||
target: 3,
|
||||
},
|
||||
{
|
||||
source: 2,
|
||||
target: 7,
|
||||
},
|
||||
{
|
||||
source: 3,
|
||||
target: 4,
|
||||
},
|
||||
{
|
||||
source: 8,
|
||||
target: 3,
|
||||
},
|
||||
{
|
||||
source: 4,
|
||||
target: 5,
|
||||
},
|
||||
{
|
||||
source: 4,
|
||||
target: 9,
|
||||
},
|
||||
{
|
||||
source: 5,
|
||||
target: 10,
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
console.log(data);
|
||||
// List of node names
|
||||
var allNodes = data.nodes.map(function (d) {
|
||||
return d.name;
|
||||
});
|
||||
|
||||
// A linear scale to position the nodes on the X axis
|
||||
var x = d3.scalePoint().range([0, width]).domain(allNodes);
|
||||
|
||||
// Add the circle for the nodes
|
||||
svg
|
||||
.selectAll("mynodes")
|
||||
.data(data.nodes)
|
||||
.enter()
|
||||
.append("circle")
|
||||
.attr("cx", function (d) {
|
||||
return x(d.name);
|
||||
})
|
||||
.attr("cy", height - 30)
|
||||
.attr("r", 8)
|
||||
.style("fill", "#69b3a2");
|
||||
|
||||
// And give them a label
|
||||
svg
|
||||
.selectAll("mylabels")
|
||||
.data(data.nodes)
|
||||
.enter()
|
||||
.append("text")
|
||||
.attr("x", function (d) {
|
||||
return x(d.name);
|
||||
})
|
||||
.attr("y", height - 10)
|
||||
.text(function (d) {
|
||||
return d.name;
|
||||
})
|
||||
.style("text-anchor", "middle");
|
||||
|
||||
// Add links between nodes. Here is the tricky part.
|
||||
// In my input data, links are provided between nodes -id-, NOT between node names.
|
||||
// So I have to do a link between this id and the name
|
||||
var idToNode = {};
|
||||
data.nodes.forEach(function (n) {
|
||||
idToNode[n.id] = n;
|
||||
});
|
||||
// Cool, now if I do idToNode["2"].name I've got the name of the node with id 2
|
||||
|
||||
// Add the links
|
||||
svg
|
||||
.selectAll("mylinks")
|
||||
.data(data.links)
|
||||
.enter()
|
||||
.append("path")
|
||||
.attr("d", function (d) {
|
||||
let start = x(idToNode[d.source].name);
|
||||
// X position of start node on the X axis
|
||||
let end = x(idToNode[d.target].name);
|
||||
// X position of end node
|
||||
return (
|
||||
[
|
||||
"M",
|
||||
start,
|
||||
height - 30,
|
||||
// the arc starts at the coordinate x=start, y=height-30 (where the starting node is)
|
||||
"A",
|
||||
// This means we're gonna build an elliptical arc
|
||||
(start - end) / 2,
|
||||
",",
|
||||
// Next 2 lines are the coordinates of the inflexion point. Height of this point is proportional with start - end distance
|
||||
(start - end) / 2,
|
||||
0,
|
||||
0,
|
||||
",",
|
||||
start < end ? 1 : 0,
|
||||
end,
|
||||
",",
|
||||
height - 30,
|
||||
]
|
||||
// We always want the arc on top. So if end is before start, putting 0 here turn the arc upside down.
|
||||
.join(" ")
|
||||
);
|
||||
})
|
||||
.style("fill", "none")
|
||||
.attr("stroke", "black");
|
||||
|
||||
// labels for links
|
||||
svg
|
||||
.selectAll("mylinks")
|
||||
.data(data.links)
|
||||
.enter()
|
||||
.append("text")
|
||||
.attr("x", function (d) {
|
||||
let start = x(idToNode[d.source].name);
|
||||
// X position of start node on the X axis
|
||||
let end = x(idToNode[d.target].name);
|
||||
// X position of end node
|
||||
return start + (end - start) / 2;
|
||||
})
|
||||
.attr("y", function (d) {
|
||||
let start = x(idToNode[d.source].name);
|
||||
// X position of start node on the X axis
|
||||
let end = x(idToNode[d.target].name);
|
||||
// X position of end node
|
||||
return height - 30 - Math.abs(start - end) / 2; //height-30
|
||||
})
|
||||
.text(function (d) {
|
||||
return `${idToNode[d.source].name}-${idToNode[d.target].name}`;
|
||||
})
|
||||
.style("text-anchor", "top");
|
||||
|
||||
svg
|
||||
.selectAll("text")
|
||||
.data(data.links)
|
||||
.enter()
|
||||
.append("text")
|
||||
.attr("x", function (d) {
|
||||
return d.source.x + (d.target.x - d.source.x) / 2;
|
||||
})
|
||||
.attr("y", function (d) {
|
||||
return d.source.y + (d.target.y - d.source.y) / 2;
|
||||
})
|
||||
.text(function (d) {
|
||||
return d.something;
|
||||
});
|
||||
}
|
||||
|
||||
export function D3Experiment() {
|
||||
useEffect(() => {
|
||||
drawGraph();
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<div>
|
||||
<div id="chart"></div>
|
||||
<div id="circles"></div>
|
||||
<div id="graph"></div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default D3Experiment;
|
||||
|
|
@ -1,109 +0,0 @@
|
|||
import React, { useState } from "react";
|
||||
|
||||
export function DataSetChanger({ handleSubmit }) {
|
||||
let [value, setValue] = useState(`[
|
||||
{
|
||||
"name": "Some element. The name field is necessary",
|
||||
"url": "http://www.example.com",
|
||||
"somethirdfield": "a"
|
||||
},
|
||||
{
|
||||
"name": "Another element",
|
||||
"url": "http://www.example1.com",
|
||||
"somethirdfield": "b"
|
||||
},
|
||||
{
|
||||
"name": "A third element",
|
||||
"url": "http://www.example2.com",
|
||||
"isReferenceValue": true,
|
||||
"somethirdfield": "c"
|
||||
}
|
||||
]`);
|
||||
const [displayingDoneMessage, setDisplayingDoneMessage] = useState(false);
|
||||
const [displayingDoneMessageTimer, setDisplayingDoneMessageTimer] =
|
||||
useState(null);
|
||||
|
||||
let handleChange = (event) => {
|
||||
setValue(event.target.value);
|
||||
};
|
||||
|
||||
let handleSubmitInner = (event) => {
|
||||
clearTimeout(displayingDoneMessageTimer);
|
||||
event.preventDefault();
|
||||
//console.log(event)
|
||||
console.log("value@handleSubmitInner@DataSetChanger");
|
||||
//console.log(typeof(value));
|
||||
console.log(value);
|
||||
try {
|
||||
let newData = JSON.parse(value);
|
||||
//console.log(typeof(newData))
|
||||
//console.log(newData)
|
||||
handleSubmit(newData);
|
||||
if (!newData.length || newData.length < 2) {
|
||||
throw Error("Not enough objects");
|
||||
}
|
||||
setDisplayingDoneMessage(true);
|
||||
let timer = setTimeout(() => setDisplayingDoneMessage(false), 3000);
|
||||
setDisplayingDoneMessageTimer(timer);
|
||||
} catch (error) {
|
||||
setDisplayingDoneMessage(false);
|
||||
//alert(error)
|
||||
//console.log(error)
|
||||
let substituteText = `Error: ${error.message}
|
||||
|
||||
Try something like:
|
||||
[
|
||||
{
|
||||
"name": "Some element. The name field is necessary",
|
||||
"url": "http://www.example.com",
|
||||
"somethirdfield": "a"
|
||||
},
|
||||
{
|
||||
"name": "Another element",
|
||||
"url": "http://www.example1.com",
|
||||
"somethirdfield": "b"
|
||||
},
|
||||
{
|
||||
"name": "Another element",
|
||||
"url": "http://www.example2.com",
|
||||
"isReferenceValue": true,
|
||||
"somethirdfield": "c"
|
||||
}
|
||||
]
|
||||
|
||||
Your old input was: ${value}`;
|
||||
setValue(substituteText);
|
||||
}
|
||||
};
|
||||
return (
|
||||
<form onSubmit={handleSubmitInner} className="inline">
|
||||
<br />
|
||||
<br />
|
||||
<textarea
|
||||
value={value}
|
||||
onChange={handleChange}
|
||||
rows="10"
|
||||
cols="50"
|
||||
className=""
|
||||
/>
|
||||
<br />
|
||||
<button
|
||||
className="bg-transparent hover:bg-blue-500 text-blue-700 font-semibold hover:text-white py-2 px-4 border border-blue-500 hover:border-transparent rounded mt-5 p-10"
|
||||
onClick={handleSubmitInner}
|
||||
>
|
||||
Change dataset
|
||||
</button>
|
||||
|
||||
<button
|
||||
className={
|
||||
displayingDoneMessage
|
||||
? "bg-transparent text-blue-700 font-semibold py-2 px-4 border border-blue-500 rounded mt-5 p-10"
|
||||
: "hidden"
|
||||
}
|
||||
>
|
||||
Done!
|
||||
</button>
|
||||
</form>
|
||||
);
|
||||
}
|
||||
|
|
@ -1,30 +0,0 @@
|
|||
import React from "react";
|
||||
import ReactMarkdown from "react-markdown";
|
||||
import gfm from "remark-gfm";
|
||||
|
||||
if (!String.prototype.replaceAll) {
|
||||
String.prototype.replaceAll = function (str, newStr) {
|
||||
// If a regex pattern
|
||||
if (
|
||||
Object.prototype.toString.call(str).toLowerCase() === "[object regexp]"
|
||||
) {
|
||||
return this.replace(str, newStr);
|
||||
}
|
||||
|
||||
// If a string
|
||||
return this.replace(new RegExp(str, "g"), newStr);
|
||||
};
|
||||
}
|
||||
|
||||
export function DisplayAsMarkdown({ markdowntext, className }) {
|
||||
//console.log(markdowntext)
|
||||
markdowntext = markdowntext.replaceAll("\n", "\n\n");
|
||||
return (
|
||||
<ReactMarkdown
|
||||
plugins={[gfm]}
|
||||
children={markdowntext}
|
||||
className={className}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
|
@ -1,44 +0,0 @@
|
|||
import React from "react";
|
||||
|
||||
let capitalizeFirstLetter = (string) =>
|
||||
string.charAt(0).toUpperCase() + string.slice(1);
|
||||
|
||||
export function DisplayElement({ element }) {
|
||||
let otherkeys = Object.keys(element).filter(
|
||||
(key) =>
|
||||
key != "name" && key != "url" && key != "id" && key != "isReferenceValue"
|
||||
);
|
||||
let othervalues = otherkeys.map((key) => element[key]);
|
||||
let otherpairs = otherkeys.map((key, i) => ({
|
||||
key: capitalizeFirstLetter(key),
|
||||
value: othervalues[i],
|
||||
}));
|
||||
|
||||
if (element.url) {
|
||||
return (
|
||||
<div>
|
||||
{/*<a href={element.url} target="_blank">*/}
|
||||
<h2>{`${element.name}`}</h2>
|
||||
{/*</a>*/}
|
||||
{otherpairs.map((pair) => (
|
||||
<p key={pair.value}>{`${pair.key}: ${pair.value}`}</p>
|
||||
))}
|
||||
<p>
|
||||
<a href={element.url} target="_blank">
|
||||
More info
|
||||
</a>
|
||||
</p>
|
||||
</div>
|
||||
);
|
||||
} else {
|
||||
return (
|
||||
<div>
|
||||
<h2>{`${element.name}`}</h2>
|
||||
{otherpairs.map((pair) => (
|
||||
<p key={pair.value}>{`${pair.key}: ${pair.value}`}</p>
|
||||
))}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,415 +0,0 @@
|
|||
/* Imports*/
|
||||
import React from "react";
|
||||
import {
|
||||
numToAlphabeticalString,
|
||||
formatLargeOrSmall,
|
||||
avg,
|
||||
hackyGeomMean,
|
||||
getCoefficientOfVariation,
|
||||
} from "../lib/utils.js";
|
||||
|
||||
/* Functions */
|
||||
|
||||
const pathPlusLink = (pathSoFar, link) => {
|
||||
return [...pathSoFar, link];
|
||||
// previously: pathSoFar.concat(link).flat()
|
||||
// Note that concat is not destructive
|
||||
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/concat
|
||||
};
|
||||
|
||||
async function findPathsWithoutPrunning({
|
||||
sourceElementId,
|
||||
targetElementId,
|
||||
maxLengthOfPath,
|
||||
pathSoFar,
|
||||
links,
|
||||
nodes,
|
||||
}) {
|
||||
// This is an un-used function which might make findPaths more understandable
|
||||
// It uses the same recursive functionality
|
||||
// but has no path prunning
|
||||
let paths = [];
|
||||
|
||||
/* Path traversing */
|
||||
if (maxLengthOfPath > 0) {
|
||||
for (let link of links) {
|
||||
// vs let link of linksNow in findPaths
|
||||
if (
|
||||
(link.source == sourceElementId && link.target == targetElementId) ||
|
||||
(link.source == targetElementId && link.target == sourceElementId)
|
||||
) {
|
||||
// direct Path
|
||||
let newPath = pathPlusLink(pathSoFar, link);
|
||||
paths.push(newPath);
|
||||
} else if (link.source == sourceElementId) {
|
||||
let newPaths = await findPaths({
|
||||
pathSoFar: pathPlusLink(pathSoFar, link),
|
||||
maxLengthOfPath: maxLengthOfPath - 1,
|
||||
sourceElementId: link.target,
|
||||
targetElementId,
|
||||
links: links, // vs let link of linksInner in findPaths
|
||||
nodes,
|
||||
});
|
||||
if (newPaths.length != 0) {
|
||||
paths.push(...newPaths);
|
||||
}
|
||||
} else if (link.target == sourceElementId) {
|
||||
let newPaths = await findPaths({
|
||||
pathSoFar: pathPlusLink(pathSoFar, link),
|
||||
maxLengthOfPath: maxLengthOfPath - 1,
|
||||
sourceElementId: link.source,
|
||||
targetElementId,
|
||||
links: links, // vs let link of linksInner in findPaths
|
||||
nodes,
|
||||
});
|
||||
if (newPaths.length != 0) {
|
||||
paths.push(...newPaths);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return paths;
|
||||
}
|
||||
|
||||
async function findPaths({
|
||||
sourceElementId,
|
||||
sourceElementPosition,
|
||||
targetElementId,
|
||||
targetElementPosition,
|
||||
maxLengthOfPath,
|
||||
pathSoFar,
|
||||
links,
|
||||
nodes,
|
||||
}) {
|
||||
// This is the key path finding function
|
||||
// It finds the path from one element to another, recursively
|
||||
// It used to be very computationally expensive until I added
|
||||
// the path prunning step: Instead of traversing all links,
|
||||
// traverse only those which are between the origin and target links
|
||||
// this requires us to have a notion of "between"
|
||||
|
||||
let paths = [];
|
||||
|
||||
/* Path prunning*/
|
||||
let minPos = Math.min(sourceElementPosition, targetElementPosition);
|
||||
let maxPos = Math.max(sourceElementPosition, targetElementPosition);
|
||||
let linksInner = links.filter(
|
||||
(link) =>
|
||||
minPos <= link.sourceElementPosition &&
|
||||
link.sourceElementPosition <= maxPos &&
|
||||
minPos <= link.targetElementPosition &&
|
||||
link.targetElementPosition <= maxPos
|
||||
);
|
||||
let linksNow = linksInner.filter(
|
||||
(link) => link.source == sourceElementId || link.target == sourceElementId
|
||||
);
|
||||
|
||||
/* Path traversing */
|
||||
if (maxLengthOfPath > 0) {
|
||||
for (let link of linksNow) {
|
||||
if (
|
||||
(link.source == sourceElementId && link.target == targetElementId) ||
|
||||
(link.source == targetElementId && link.target == sourceElementId)
|
||||
) {
|
||||
// direct Path
|
||||
let newPath = pathPlusLink(pathSoFar, link);
|
||||
paths.push(newPath);
|
||||
} else if (link.source == sourceElementId) {
|
||||
let newPaths = await findPaths({
|
||||
pathSoFar: pathPlusLink(pathSoFar, link),
|
||||
maxLengthOfPath: maxLengthOfPath - 1,
|
||||
sourceElementPosition: link.sourceElementPosition,
|
||||
sourceElementId: link.target,
|
||||
targetElementId,
|
||||
targetElementPosition,
|
||||
links: linksInner,
|
||||
nodes,
|
||||
});
|
||||
if (newPaths.length != 0) {
|
||||
paths.push(...newPaths);
|
||||
}
|
||||
} else if (link.target == sourceElementId) {
|
||||
let newPaths = await findPaths({
|
||||
pathSoFar: pathPlusLink(pathSoFar, link),
|
||||
maxLengthOfPath: maxLengthOfPath - 1,
|
||||
sourceElementPosition: link.sourceElementPosition,
|
||||
sourceElementId: link.source,
|
||||
targetElementPosition,
|
||||
targetElementId,
|
||||
links: linksInner,
|
||||
nodes,
|
||||
});
|
||||
if (newPaths.length != 0) {
|
||||
paths.push(...newPaths);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return paths;
|
||||
}
|
||||
|
||||
async function findDistancesForElement({
|
||||
sourceElementId,
|
||||
sourceElementPosition,
|
||||
targetElementId,
|
||||
targetElementPosition,
|
||||
nodes,
|
||||
links,
|
||||
}) {
|
||||
// This function gets all possible paths using findPaths
|
||||
// then orders them correctly in the for loop
|
||||
// (by flipping the distance to 1/distance when necessary)
|
||||
// and then gets the array of weights for the different paths.
|
||||
console.log(
|
||||
`findDistance@findPaths.js from ${sourceElementPosition} to ${targetElementPosition}`
|
||||
);
|
||||
|
||||
let maxLengthOfPath = Math.abs(sourceElementPosition - targetElementPosition);
|
||||
let paths = await findPaths({
|
||||
sourceElementId,
|
||||
sourceElementPosition,
|
||||
targetElementId,
|
||||
targetElementPosition,
|
||||
links,
|
||||
nodes,
|
||||
maxLengthOfPath,
|
||||
pathSoFar: [],
|
||||
});
|
||||
|
||||
let weights = [];
|
||||
for (let path of paths) {
|
||||
let currentSource = sourceElementId;
|
||||
let weight = 1;
|
||||
for (let element of path) {
|
||||
let distance = 0;
|
||||
if (element.source == currentSource) {
|
||||
distance = element.distance;
|
||||
currentSource = element.target;
|
||||
} else if (element.target == currentSource) {
|
||||
distance = 1 / Number(element.distance);
|
||||
currentSource = element.source;
|
||||
}
|
||||
weight = weight * distance;
|
||||
}
|
||||
weights.push(weight);
|
||||
}
|
||||
return weights;
|
||||
}
|
||||
|
||||
async function findDistancesForAllElements({ nodes, links }) {
|
||||
// legacy. I used to need a somewhat hardcoded reference point. Now that's not necessary.
|
||||
// Simple wrapper function around findDistance
|
||||
// Needs to find the reference point first
|
||||
console.log("findDistancesForAllElements@findPaths.js");
|
||||
/* Get or build reference element */
|
||||
let referenceElements = nodes.filter((x) => x.isReferenceValue);
|
||||
let midpoint = Math.round(nodes.length / 2);
|
||||
let referenceElement =
|
||||
referenceElements.length > 0 ? referenceElements[0] : nodes[midpoint];
|
||||
console.log(`referenceElement.position: ${referenceElement.position}`);
|
||||
|
||||
/* Get distances. */
|
||||
let distancesArray = nodes.map((node) => {
|
||||
if (node.isReferenceValue || node.id == referenceElement.id) {
|
||||
return [1];
|
||||
} else {
|
||||
console.log("node");
|
||||
console.log(node);
|
||||
let distancesForElement = findDistancesForElement({
|
||||
sourceElementId: referenceElement.id,
|
||||
sourceElementPosition: referenceElement.position,
|
||||
targetElementId: node.id,
|
||||
targetElementPosition: node.position,
|
||||
nodes: nodes,
|
||||
links: links,
|
||||
});
|
||||
return distancesForElement;
|
||||
}
|
||||
});
|
||||
distancesArray = await Promise.all(distancesArray);
|
||||
return distancesArray;
|
||||
}
|
||||
|
||||
async function findDistancesFromAllElementsToReferencePoint({
|
||||
nodes,
|
||||
links,
|
||||
referenceElement,
|
||||
}) {
|
||||
// Simple wrapper function around findDistance
|
||||
// Needs to find the reference point first
|
||||
console.log("findDistancesForAllElements@findPaths.js");
|
||||
/* Get or build reference element */
|
||||
let midpoint = Math.round(nodes.length / 2);
|
||||
referenceElement = referenceElement || nodes[midpoint];
|
||||
console.log(`referenceElement.position: ${referenceElement.position}`);
|
||||
|
||||
/* Get distances. */
|
||||
let distancesArray = nodes.map((node) => {
|
||||
if (node.id == referenceElement.id) {
|
||||
return [1];
|
||||
} else {
|
||||
console.log("node");
|
||||
console.log(node);
|
||||
let distancesForElement = findDistancesForElement({
|
||||
sourceElementId: referenceElement.id,
|
||||
sourceElementPosition: referenceElement.position,
|
||||
targetElementId: node.id,
|
||||
targetElementPosition: node.position,
|
||||
nodes: nodes,
|
||||
links: links,
|
||||
});
|
||||
return distancesForElement;
|
||||
}
|
||||
});
|
||||
distancesArray = await Promise.all(distancesArray);
|
||||
return distancesArray;
|
||||
}
|
||||
|
||||
async function findDistancesFromAllElementsToAllReferencePoints({
|
||||
nodes,
|
||||
links,
|
||||
}) {
|
||||
let nodes2 = nodes.map((node) => ({ ...node, isReferenceValue: false }));
|
||||
let distancesForAllElements = Array(nodes.length);
|
||||
for (let i = 0; i < nodes.length; i++) {
|
||||
distancesForAllElements[i] = [];
|
||||
}
|
||||
for (let node of nodes2) {
|
||||
let distancesFromNode = await findDistancesFromAllElementsToReferencePoint({
|
||||
nodes,
|
||||
links,
|
||||
referenceElement: node,
|
||||
});
|
||||
// alert(`distancesFromNode.length: ${distancesFromNode.length}`);
|
||||
distancesForAllElements = distancesForAllElements.map((arr, i) => {
|
||||
return !!arr && arr.length > 0
|
||||
? [...arr, ...distancesFromNode[i]]
|
||||
: distancesFromNode[i];
|
||||
});
|
||||
}
|
||||
return distancesForAllElements;
|
||||
}
|
||||
|
||||
export async function buildRows({
|
||||
isListOrdered,
|
||||
orderedList,
|
||||
listOfElements,
|
||||
links,
|
||||
rows,
|
||||
setTableRows,
|
||||
}) {
|
||||
console.log("buildRows@findPaths.js");
|
||||
// This function is used in pages/comparisonView.js to create the rows that will be displayed.
|
||||
// it is in there because it needs to be deployed after isListOrdered becomes true,
|
||||
// and using an useEffect inside CreateTable was too messy.
|
||||
if (
|
||||
isListOrdered &&
|
||||
!(orderedList.length < listOfElements.length) &&
|
||||
rows.length == 0
|
||||
) {
|
||||
let nodes = [];
|
||||
let positionDictionary = {};
|
||||
orderedList.forEach((id, pos) => {
|
||||
nodes.push({ ...listOfElements[id], position: pos });
|
||||
positionDictionary[id] = pos;
|
||||
});
|
||||
links = links.map((link) => ({
|
||||
...link,
|
||||
sourceElementPosition: positionDictionary[link.source],
|
||||
targetElementPosition: positionDictionary[link.target],
|
||||
}));
|
||||
|
||||
let distances = await findDistancesFromAllElementsToAllReferencePoints({
|
||||
nodes,
|
||||
links,
|
||||
}); //findDistancesForAllElements({ nodes, links });
|
||||
rows = nodes.map((element, i) => ({
|
||||
id: numToAlphabeticalString(element.position),
|
||||
position: element.position,
|
||||
name: element.name,
|
||||
distances: distances[i],
|
||||
}));
|
||||
console.log(rows);
|
||||
setTableRows(rows);
|
||||
}
|
||||
}
|
||||
|
||||
export function CreateTable({ tableRows }) {
|
||||
/* This function receives a list of rows, and displays them nicely. */
|
||||
function abridgeArrayAndDisplay(array) {
|
||||
let newArray;
|
||||
let formatForDisplay;
|
||||
if (array.length > 10) {
|
||||
newArray = array.slice(0, 9);
|
||||
formatForDisplay = newArray.map((d) => formatLargeOrSmall(d));
|
||||
formatForDisplay[9] = "...";
|
||||
} else {
|
||||
newArray = array;
|
||||
formatForDisplay = newArray.map((d) => formatLargeOrSmall(d));
|
||||
}
|
||||
let result = JSON.stringify(formatForDisplay, null, 2).replaceAll(`"`, "");
|
||||
return result;
|
||||
}
|
||||
return (
|
||||
<div className="w-full">
|
||||
<table className="table-auto">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Id</th>
|
||||
<th> </th>
|
||||
<th>Position</th>
|
||||
<th> </th>
|
||||
<th>Element</th>
|
||||
<th> </th>
|
||||
<th>Possible relative values</th>
|
||||
<th> </th>
|
||||
<th>geomMean(relative values)</th>
|
||||
<th>Coefficient of variation</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{tableRows.map((row) => (
|
||||
<tr key={row.id}>
|
||||
<td className="">{row.id}</td>
|
||||
<td> </td>
|
||||
<td className="">{row.position}</td>
|
||||
<td> </td>
|
||||
<td className="">{row.name}</td>
|
||||
<td> </td>
|
||||
<td className="">{abridgeArrayAndDisplay(row.distances)}</td>
|
||||
<td> </td>
|
||||
<td className="">
|
||||
{formatLargeOrSmall(hackyGeomMean(row.distances))}
|
||||
</td>
|
||||
<td className="">
|
||||
{formatLargeOrSmall(getCoefficientOfVariation(row.distances))}
|
||||
</td>
|
||||
</tr>
|
||||
))}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
/* Testing */
|
||||
//import fs from 'fs';
|
||||
//import path from 'path';
|
||||
/*
|
||||
const directory = path.join(process.cwd(),"pages")
|
||||
let links = JSON.parse(fs.readFileSync(path.join(directory, 'distancesExample.json'), 'utf8'));
|
||||
let nodes = JSON.parse(fs.readFileSync(path.join(directory, 'listOfPosts.json'), 'utf8'));
|
||||
|
||||
let paths = findPaths({sourceElementId:2, targetElementId:0, pathSoFar: [], links, nodes, maxLengthOfPath: 2})
|
||||
console.log(JSON.stringify(paths, null, 2))
|
||||
*/
|
||||
/*
|
||||
let paths = findPaths({sourceElementId:2, targetElementId:0, links, nodes})
|
||||
console.log(JSON.stringify(paths, null, 2))
|
||||
*/
|
||||
/*
|
||||
let distances = findDistance({sourceElementId:2, targetElementId:4, links, nodes})
|
||||
console.log(distances)
|
||||
*/
|
|
@ -1,186 +0,0 @@
|
|||
import React, { useState, useEffect } from "react";
|
||||
import * as d3 from "d3";
|
||||
import {
|
||||
toLocale,
|
||||
truncateValueForDisplay,
|
||||
numToAlphabeticalString,
|
||||
formatLargeOrSmall,
|
||||
} from "./utils.js";
|
||||
|
||||
const displayWidthPercentage = 0.85; // 0.85; // 0.7
|
||||
|
||||
let getlength = (number) => number.toString().length;
|
||||
|
||||
export function removeOldSvg() {
|
||||
d3.select("#graph").select("svg").remove();
|
||||
}
|
||||
|
||||
function drawGraphInner({ nodes, links }) {
|
||||
// List of node ids for convenience
|
||||
var nodeids = nodes.map((node) => node.id);
|
||||
var positionById = {};
|
||||
nodeids.forEach((nodeid, i) => (positionById[nodeid] = i));
|
||||
console.log("NodeIds/positionById");
|
||||
console.log(nodeids);
|
||||
console.log(positionById);
|
||||
|
||||
// Calculate the dimensions
|
||||
// let margin = { top: 0, right: 30, bottom: 20, left: 30 };
|
||||
// let width = 900 - margin.left - margin.right;
|
||||
|
||||
let initialWindowWidth = window.innerWidth;
|
||||
let margin = { top: 0, right: 10, bottom: 20, left: 10 };
|
||||
let width =
|
||||
initialWindowWidth * displayWidthPercentage - margin.left - margin.right;
|
||||
|
||||
var x = d3.scalePoint().range([0, width]).domain(nodeids);
|
||||
|
||||
let heights = links.map((link) => {
|
||||
let start = x(positionById[link.source]);
|
||||
let end = x(positionById[link.target]);
|
||||
return Math.abs(start - end) / 2 + 70; // Magic constant.
|
||||
});
|
||||
console.log(heights);
|
||||
let maxheight = Math.max(...heights);
|
||||
let height = maxheight - margin.top - margin.bottom;
|
||||
console.log(`height: ${height}`);
|
||||
|
||||
// Build the d3 graph
|
||||
|
||||
removeOldSvg();
|
||||
let svg = d3
|
||||
.select("#graph")
|
||||
.append("svg")
|
||||
.attr("width", width + margin.left + margin.right)
|
||||
.attr("height", height + margin.top + margin.bottom)
|
||||
.append("g")
|
||||
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
|
||||
|
||||
// A linear scale to position the nodes on the X axis
|
||||
|
||||
// Add the circle for the nodes
|
||||
svg
|
||||
.selectAll("mynodes")
|
||||
.data(nodes)
|
||||
.enter()
|
||||
.append("circle")
|
||||
.attr("cx", function (d) {
|
||||
return x(d.id);
|
||||
})
|
||||
.attr("cy", height - 30)
|
||||
.attr("r", 8)
|
||||
.style("fill", "#69b3a2");
|
||||
|
||||
// And give them a label
|
||||
svg
|
||||
.selectAll("mylabels")
|
||||
.data(nodes)
|
||||
.enter()
|
||||
.append("text")
|
||||
.attr("x", function (d) {
|
||||
return x(d.id);
|
||||
})
|
||||
.attr("y", height - 10)
|
||||
.text(function (d) {
|
||||
return numToAlphabeticalString(d.position);
|
||||
})
|
||||
.style("text-anchor", "middle");
|
||||
|
||||
// Add the links
|
||||
svg
|
||||
.selectAll("mylinks")
|
||||
.data(links)
|
||||
.enter()
|
||||
.append("path")
|
||||
.attr("d", function (d) {
|
||||
let start = x(d.source);
|
||||
// X position of start node on the X axis
|
||||
let end = x(d.target);
|
||||
// X position of end node
|
||||
return (
|
||||
[
|
||||
"M",
|
||||
start,
|
||||
height - 30,
|
||||
// the arc starts at the coordinate x=start, y=height-30 (where the starting node is)
|
||||
"A",
|
||||
// This means we're gonna build an elliptical arc
|
||||
(start - end) / 2,
|
||||
",",
|
||||
// Next 2 lines are the coordinates of the inflexion point. Height of this point is proportional with start - end distance
|
||||
(start - end) / 2,
|
||||
0,
|
||||
0,
|
||||
",",
|
||||
start < end ? 1 : 0,
|
||||
end,
|
||||
",",
|
||||
height - 30,
|
||||
]
|
||||
// We always want the arc on top. So if end is before start, putting 0 here turn the arc upside down.
|
||||
.join(" ")
|
||||
);
|
||||
})
|
||||
.style("fill", "none")
|
||||
.attr("stroke", "green"); // black
|
||||
|
||||
// labels for links
|
||||
// smaller font.
|
||||
svg
|
||||
.selectAll("mylinks")
|
||||
.data(links)
|
||||
.enter()
|
||||
.append("text")
|
||||
.attr("x", function (d) {
|
||||
let start = x(d.source);
|
||||
// X position of start node on the X axis
|
||||
let end = x(d.target);
|
||||
// X position of end node
|
||||
return start + (end - start) / 2; //-4*getlength(d.distance)
|
||||
})
|
||||
.attr("y", function (d) {
|
||||
let start = x(d.source);
|
||||
// X position of start node on the X axis
|
||||
let end = x(d.target);
|
||||
// X position of end node
|
||||
return height - 36 - Math.abs(start - end) / 2; //height-30
|
||||
})
|
||||
.text(function (d) {
|
||||
let distanceFormatted = formatLargeOrSmall(Number(d.distance));
|
||||
return distanceFormatted;
|
||||
if (d.distance == d.squiggleString || !d.squiggleString) {
|
||||
return distanceFormatted;
|
||||
} else {
|
||||
// return `${d.squiggleString} → ${distanceFormatted}`;
|
||||
return `(${d.squiggleString})`;
|
||||
}
|
||||
|
||||
// return (truncateValueForDisplay(Number(d.distance)))
|
||||
//return(Number(d.distance).toPrecision(2).toString())
|
||||
})
|
||||
.style("text-anchor", "middle");
|
||||
// background
|
||||
}
|
||||
|
||||
export function DrawGraph({
|
||||
isListOrdered,
|
||||
orderedList,
|
||||
listOfElements,
|
||||
links,
|
||||
}) {
|
||||
if (isListOrdered) {
|
||||
let nodes = orderedList.map((id, pos) => ({
|
||||
...listOfElements[id],
|
||||
position: pos,
|
||||
}));
|
||||
drawGraphInner({ nodes, links });
|
||||
}
|
||||
return (
|
||||
<div className="flex w-full items-center ">
|
||||
<div
|
||||
id="graph"
|
||||
className="mx-auto flex justify-center w-full bg-red"
|
||||
></div>
|
||||
</div>
|
||||
);
|
||||
}
|
|
@ -1,17 +0,0 @@
|
|||
import axios from "axios";
|
||||
|
||||
const CONNECTION_IS_ACTIVE = true;
|
||||
|
||||
export async function pushToMongo(data) {
|
||||
if (CONNECTION_IS_ACTIVE) {
|
||||
let response = await axios.post(
|
||||
"https://server.loki.red/utility-function-extractor",
|
||||
{
|
||||
data: data,
|
||||
}
|
||||
);
|
||||
console.log(response);
|
||||
}
|
||||
}
|
||||
// pushToMongo()
|
||||
|
|
@ -1,337 +0,0 @@
|
|||
import axios from "axios";
|
||||
|
||||
let data = [
|
||||
{
|
||||
source: "Thinking Fast and Slow",
|
||||
|
||||
target: "The Mathematical Theory of Communication",
|
||||
|
||||
distance: 99999.99999999999,
|
||||
|
||||
reasoning:
|
||||
"TFS: Not original work. 1 million buyers, 0.3m readers, 0.03m did anything with it long-term. Debiasing doesn't work that much. But maybe some general sanity effects.\nMTC: foundational to half of good fields. Direct applications key to telecoms and internet, AI. Is very natural and probably invented anyway, but let's ignore replaceability. ",
|
||||
},
|
||||
|
||||
{
|
||||
source: "The Global Priorities Institute's Research Agenda",
|
||||
|
||||
target: "Superintelligence",
|
||||
|
||||
distance: 100,
|
||||
|
||||
reasoning:
|
||||
"GPI: good stuff but v v hard questions read by ~200.\nSuperintelligence: Maybe 50,000 copies? associated interview tour transformed the field.",
|
||||
},
|
||||
|
||||
{
|
||||
source: "Thinking Fast and Slow",
|
||||
|
||||
target: "The Global Priorities Institute's Research Agenda",
|
||||
|
||||
distance: "100",
|
||||
|
||||
reasoning: "",
|
||||
},
|
||||
|
||||
{
|
||||
source: "The Global Priorities Institute's Research Agenda",
|
||||
|
||||
target: "The Mathematical Theory of Communication",
|
||||
|
||||
distance: 1000,
|
||||
|
||||
reasoning: "",
|
||||
},
|
||||
|
||||
{
|
||||
source: "Superintelligence",
|
||||
|
||||
target: "The Mathematical Theory of Communication",
|
||||
|
||||
distance: 10,
|
||||
|
||||
reasoning: "",
|
||||
},
|
||||
|
||||
{
|
||||
source: "Categorizing Variants of Goodhart's Law",
|
||||
|
||||
target: "The Vulnerable World Hypothesis",
|
||||
|
||||
distance: 10,
|
||||
|
||||
reasoning: "",
|
||||
},
|
||||
|
||||
{
|
||||
source: "Shallow evaluations of longtermist organizations",
|
||||
|
||||
target: "The motivated reasoning critique of effective altruism",
|
||||
|
||||
distance: 10,
|
||||
|
||||
reasoning: "",
|
||||
},
|
||||
|
||||
{
|
||||
source: "Shallow evaluations of longtermist organizations",
|
||||
|
||||
target: "Categorizing Variants of Goodhart's Law",
|
||||
|
||||
distance: 100,
|
||||
|
||||
reasoning: "",
|
||||
},
|
||||
|
||||
{
|
||||
source: "The motivated reasoning critique of effective altruism",
|
||||
|
||||
target: "Categorizing Variants of Goodhart's Law",
|
||||
|
||||
distance: 10,
|
||||
|
||||
reasoning: "",
|
||||
},
|
||||
|
||||
{
|
||||
source: "Shallow evaluations of longtermist organizations",
|
||||
|
||||
target: "Thinking Fast and Slow",
|
||||
|
||||
distance: 10,
|
||||
|
||||
reasoning: "",
|
||||
},
|
||||
|
||||
{
|
||||
source: "Thinking Fast and Slow",
|
||||
|
||||
target: "The motivated reasoning critique of effective altruism",
|
||||
|
||||
distance: 1,
|
||||
|
||||
reasoning: "",
|
||||
},
|
||||
|
||||
{
|
||||
source: "The motivated reasoning critique of effective altruism",
|
||||
|
||||
target: "The Global Priorities Institute's Research Agenda",
|
||||
|
||||
distance: 1000,
|
||||
|
||||
reasoning: "",
|
||||
},
|
||||
|
||||
{
|
||||
source: "Categorizing Variants of Goodhart's Law",
|
||||
|
||||
target: "The Global Priorities Institute's Research Agenda",
|
||||
|
||||
distance: 100,
|
||||
|
||||
reasoning: "",
|
||||
},
|
||||
|
||||
{
|
||||
source: "The Vulnerable World Hypothesis",
|
||||
|
||||
target: "The Global Priorities Institute's Research Agenda",
|
||||
|
||||
distance: 10,
|
||||
|
||||
reasoning: "",
|
||||
},
|
||||
|
||||
{
|
||||
source: "Reversals in Psychology",
|
||||
|
||||
target: "A Model of Patient Spending and Movement Building",
|
||||
|
||||
distance: 10,
|
||||
|
||||
reasoning:
|
||||
"RiP: Cleaning up 10,000 people's brains a bit.\nMPS: far more important topic",
|
||||
},
|
||||
|
||||
{
|
||||
source: "Database of orgs relevant to longtermist/x-risk work",
|
||||
|
||||
target:
|
||||
"What are some low-information priors that you find practically useful for thinking about the world?",
|
||||
|
||||
distance: "5",
|
||||
|
||||
reasoning:
|
||||
"\nDatabase just saves a bit of time, maybe 100 counterfactual applications",
|
||||
},
|
||||
|
||||
{
|
||||
source: "Reversals in Psychology",
|
||||
|
||||
target: "Database of orgs relevant to longtermist/x-risk work",
|
||||
|
||||
distance: 1,
|
||||
|
||||
reasoning: "",
|
||||
},
|
||||
|
||||
{
|
||||
source: "Database of orgs relevant to longtermist/x-risk work",
|
||||
|
||||
target: "A Model of Patient Spending and Movement Building",
|
||||
|
||||
distance: 10,
|
||||
|
||||
reasoning: "",
|
||||
},
|
||||
|
||||
{
|
||||
source:
|
||||
"What are some low-information priors that you find practically useful for thinking about the world?",
|
||||
|
||||
target: "A Model of Patient Spending and Movement Building",
|
||||
|
||||
distance: 2,
|
||||
|
||||
reasoning: "",
|
||||
},
|
||||
|
||||
{
|
||||
source: "Center for Election Science EA Wiki stub",
|
||||
|
||||
target:
|
||||
"Extinguishing or preventing coal seam fires is a potential cause area",
|
||||
|
||||
distance: 1000,
|
||||
|
||||
reasoning: "",
|
||||
},
|
||||
|
||||
{
|
||||
source: "A comment on setting up a charity",
|
||||
|
||||
target: "Center for Election Science EA Wiki stub",
|
||||
|
||||
distance: 10,
|
||||
|
||||
reasoning: "",
|
||||
},
|
||||
|
||||
{
|
||||
source: "A comment on setting up a charity",
|
||||
|
||||
target: "Reversals in Psychology",
|
||||
|
||||
distance: 200,
|
||||
|
||||
reasoning: "",
|
||||
},
|
||||
|
||||
{
|
||||
source: "Center for Election Science EA Wiki stub",
|
||||
|
||||
target: "Reversals in Psychology",
|
||||
|
||||
distance: 20,
|
||||
|
||||
reasoning: "",
|
||||
},
|
||||
|
||||
{
|
||||
source: "Reversals in Psychology",
|
||||
|
||||
target:
|
||||
"Extinguishing or preventing coal seam fires is a potential cause area",
|
||||
|
||||
distance: "50",
|
||||
|
||||
reasoning: "",
|
||||
},
|
||||
|
||||
{
|
||||
source: "Database of orgs relevant to longtermist/x-risk work",
|
||||
|
||||
target:
|
||||
"Extinguishing or preventing coal seam fires is a potential cause area",
|
||||
|
||||
distance: "50",
|
||||
|
||||
reasoning: "",
|
||||
},
|
||||
|
||||
{
|
||||
source:
|
||||
"What are some low-information priors that you find practically useful for thinking about the world?",
|
||||
|
||||
target:
|
||||
"Extinguishing or preventing coal seam fires is a potential cause area",
|
||||
|
||||
distance: "10",
|
||||
|
||||
reasoning: "",
|
||||
},
|
||||
|
||||
{
|
||||
source: "A Model of Patient Spending and Movement Building",
|
||||
|
||||
target:
|
||||
"Extinguishing or preventing coal seam fires is a potential cause area",
|
||||
|
||||
distance: 1,
|
||||
|
||||
reasoning: "",
|
||||
},
|
||||
|
||||
{
|
||||
source: "A comment on setting up a charity",
|
||||
|
||||
target: "Shallow evaluations of longtermist organizations",
|
||||
|
||||
distance: 1000,
|
||||
|
||||
reasoning: "",
|
||||
},
|
||||
|
||||
{
|
||||
source: "Center for Election Science EA Wiki stub",
|
||||
|
||||
target: "Shallow evaluations of longtermist organizations",
|
||||
|
||||
distance: 100,
|
||||
|
||||
reasoning: "",
|
||||
},
|
||||
|
||||
{
|
||||
source: "Reversals in Psychology",
|
||||
|
||||
target: "Shallow evaluations of longtermist organizations",
|
||||
|
||||
distance: 100,
|
||||
|
||||
reasoning: "",
|
||||
},
|
||||
|
||||
{
|
||||
source: "Database of orgs relevant to longtermist/x-risk work",
|
||||
|
||||
target: "Shallow evaluations of longtermist organizations",
|
||||
|
||||
distance: 100,
|
||||
|
||||
reasoning: "",
|
||||
},
|
||||
];
|
||||
|
||||
async function pushToMongoManually() {
|
||||
let response = await axios.post(
|
||||
"http://metaforecast-twitter-bot.herokuapp.com/utility-function-extractor",
|
||||
{
|
||||
data: data,
|
||||
}
|
||||
);
|
||||
console.log(response);
|
||||
}
|
||||
pushToMongoManually();
|
||||
|
|
@ -1,23 +0,0 @@
|
|||
import axios from "axios";
|
||||
|
||||
export async function squiggleWrapper(input) {
|
||||
let response = await axios.post("https://server.loki.red/squiggle", {
|
||||
model: `mean(${input})`,
|
||||
});
|
||||
if (response.status == 200) {
|
||||
try {
|
||||
console.log(response.data);
|
||||
if (!!response.data && !!response.data.value) {
|
||||
// console.log(response.data.value);
|
||||
let result = response.data.value.value; //hd.VAL;
|
||||
console.log(result);
|
||||
return result;
|
||||
}
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
// squiggle("1 to 4");
|
|
@ -1,66 +0,0 @@
|
|||
/* Imports */
|
||||
import React, { useState } from "react";
|
||||
import { squiggleWrapper } from "./squiggleWrapper";
|
||||
|
||||
export function SubmitButton({
|
||||
posList,
|
||||
binaryComparisons,
|
||||
inputValue,
|
||||
reasoning,
|
||||
toComparePair,
|
||||
nextStepInput,
|
||||
dontPushSubmitButtonAnyMore,
|
||||
}) {
|
||||
// This element didn't necessarily have to exist, but it made it easier for debugging purposes
|
||||
let onClick = async (event) => {
|
||||
if (!dontPushSubmitButtonAnyMore) {
|
||||
//event.preventDefault();
|
||||
let obj = {
|
||||
posList,
|
||||
binaryComparisons,
|
||||
inputValue,
|
||||
squiggleString: inputValue,
|
||||
reasoning,
|
||||
element1: toComparePair[1],
|
||||
element2: toComparePair[0],
|
||||
};
|
||||
//
|
||||
console.log("input@SubmitInputButton");
|
||||
console.log(obj);
|
||||
if (!!Number(inputValue) && inputValue >= 0) {
|
||||
nextStepInput(obj);
|
||||
} else if (!!Number(inputValue) && inputValue < 0) {
|
||||
alert("Suport for negative numbers experimental");
|
||||
nextStepInput({
|
||||
...obj,
|
||||
inputValue: inputValue,
|
||||
squiggleString: inputValue,
|
||||
});
|
||||
} else {
|
||||
let potentialSquiggleOutput = await squiggleWrapper(inputValue);
|
||||
if (!!Number(potentialSquiggleOutput)) {
|
||||
nextStepInput({
|
||||
...obj,
|
||||
inputValue: potentialSquiggleOutput,
|
||||
squiggleString: inputValue,
|
||||
});
|
||||
} else {
|
||||
alert("Your input is not a number or a valid distribution");
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<button
|
||||
className={
|
||||
!dontPushSubmitButtonAnyMore
|
||||
? "bg-transparent hover:bg-blue-500 text-blue-700 font-semibold hover:text-white py-2 px-4 border border-blue-500 hover:border-transparent rounded mt-5"
|
||||
: "bg-transparent text-blue-700 font-semibold py-2 px-4 border border-blue-500 rounded mt-5"
|
||||
}
|
||||
onClick={onClick}
|
||||
>
|
||||
Submit
|
||||
</button>
|
||||
);
|
||||
}
|
|
@ -1,163 +0,0 @@
|
|||
import crypto from "crypto";
|
||||
|
||||
export const hashString = (string) =>
|
||||
crypto.createHash("md5").update(string).digest("hex");
|
||||
const id = (x) => x;
|
||||
export const transformSliderValueToActualValue = id;
|
||||
export const transformSliderValueToPracticalValue = id;
|
||||
|
||||
export const _transformSliderValueToActualValue = (value) => 10 ** value; //>= 2 ? Math.round(10 ** value) : Math.round(10 * 10 ** value) / 10
|
||||
export const toLocale = (x) => Number(x).toLocaleString();
|
||||
export const truncateValueForDisplay = (value) => {
|
||||
if (value > 10) {
|
||||
return Number(Math.round(value).toPrecision(2));
|
||||
} else if (value > 1) {
|
||||
return Math.round(value * 10) / 10;
|
||||
} else if (value <= 1) {
|
||||
return value;
|
||||
}
|
||||
};
|
||||
export const _transformSliderValueToPracticalValue = (value) =>
|
||||
truncateValueForDisplay(transformSliderValueToActualValue(value));
|
||||
|
||||
export function sleep(ms) {
|
||||
return new Promise((resolve) => setTimeout(resolve, ms));
|
||||
}
|
||||
|
||||
export function numToAlphabeticalString(num) {
|
||||
// https://stackoverflow.com/questions/45787459/convert-number-to-alphabet-string-javascript/45787487
|
||||
num = num + 1;
|
||||
var s = "",
|
||||
t;
|
||||
while (num > 0) {
|
||||
t = (num - 1) % 26;
|
||||
s = String.fromCharCode(65 + t) + s;
|
||||
num = ((num - t) / 26) | 0;
|
||||
}
|
||||
return `#${s}` || undefined;
|
||||
}
|
||||
|
||||
let topOutAt100AndValidate = (x) => {
|
||||
// return 10;
|
||||
if (x == x) {
|
||||
return x > 99 ? 99 : x < 0 ? 2 : x;
|
||||
} else {
|
||||
return 10;
|
||||
}
|
||||
};
|
||||
|
||||
export function formatLargeOrSmall(num) {
|
||||
let result;
|
||||
if (num >= 1) {
|
||||
result = toLocale(truncateValueForDisplay(num));
|
||||
} else if (num > 0) {
|
||||
let candidateNumSignificantDigits =
|
||||
-Math.floor(Math.log(num) / Math.log(10)) + 1;
|
||||
let numSignificantDigits = topOutAt100AndValidate(
|
||||
candidateNumSignificantDigits
|
||||
);
|
||||
result = num.toFixed(numSignificantDigits);
|
||||
} else if (-1 < num) {
|
||||
let candidateNumSignificantDigits =
|
||||
-Math.floor(Math.log(Math.abs(num)) / Math.log(10)) + 1;
|
||||
let numSignificantDigits = topOutAt100AndValidate(
|
||||
candidateNumSignificantDigits
|
||||
);
|
||||
result = num.toFixed(numSignificantDigits);
|
||||
} else if (num <= -1) {
|
||||
result = "-" + toLocale(truncateValueForDisplay(-num));
|
||||
} else {
|
||||
result = toLocale(num); //return "~0"
|
||||
}
|
||||
|
||||
console.log(`${num} -> ${result}`);
|
||||
return result;
|
||||
}
|
||||
const firstFewMaxMergeSortSequence = [
|
||||
0, 0, 1, 3, 5, 8, 11, 14, 17, 21, 25, 29, 33, 37, 41, 45, 49, 54, 59, 64, 69,
|
||||
74, 79, 84, 89, 94, 99, 104, 109, 114, 119, 124, 129, 135, 141, 147, 153, 159,
|
||||
165, 171, 177, 183, 189, 195, 201, 207, 213, 219, 225, 231, 237, 243, 249,
|
||||
255, 261, 267, 273, 279, 285,
|
||||
];
|
||||
|
||||
export function maxMergeSortSteps(n) {
|
||||
if (n < firstFewMaxMergeSortSequence.length) {
|
||||
return firstFewMaxMergeSortSequence[n];
|
||||
} else {
|
||||
return (
|
||||
maxMergeSortSteps(Math.floor(n / 2)) +
|
||||
maxMergeSortSteps(Math.ceil(n / 2)) +
|
||||
n -
|
||||
1
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export function expectedNumMergeSortSteps(n) {
|
||||
// https://cs.stackexchange.com/questions/82862/expected-number-of-comparisons-in-a-merge-step
|
||||
// n-2 for each step, so (n-2) + (n-2)/2 + (n-2)/4 + ...
|
||||
// ~ 2*(n-2) -1 = 2*n - 3
|
||||
if (n == 0) {
|
||||
return 0;
|
||||
} else if (n == 1) {
|
||||
return 0;
|
||||
} else if (n == 2) {
|
||||
return 1;
|
||||
} else if (n == 3) {
|
||||
return 2;
|
||||
} else {
|
||||
return (
|
||||
Math.ceil(n ** 2 / (n + 2)) + expectedNumMergeSortSteps(Math.ceil(n / 2))
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
let result = Math.exp(logavg / n);
|
||||
return result;
|
||||
};
|
||||
|
||||
export const hackyGeomMean = (arr) => {
|
||||
let nonPositiveNumbers = arr.filter((x) => x <= 0);
|
||||
if (nonPositiveNumbers.length == 0) {
|
||||
return geomMean(arr);
|
||||
} else {
|
||||
return avg(arr);
|
||||
}
|
||||
};
|
||||
|
||||
export function conservativeNumMergeSortSteps(n) {
|
||||
return Math.ceil((expectedNumMergeSortSteps(n) + maxMergeSortSteps(n)) / 2);
|
||||
}
|
||||
// export const geomMean = (arr) => arr.reduce((a, b) => a * b, 1); // ^ (1 / arr.length); // didn't work so well for low numbers.
|
||||
|
||||
export const increasingList = (n) => Array.from(Array(n).keys());
|
||||
|
||||
function getStdev(arr) {
|
||||
if (Array.isArray(arr) && arr.length > 0) {
|
||||
const n = arr.length;
|
||||
const mean = arr.reduce((a, b) => a + b) / n;
|
||||
return Math.sqrt(
|
||||
arr.map((x) => Math.pow(x - mean, 2)).reduce((a, b) => a + b) / n
|
||||
);
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
export const getCoefficientOfVariation = (arr) => {
|
||||
let nonPositiveNumbers = arr.filter((x) => x <= 0);
|
||||
if (nonPositiveNumbers.length == 0) {
|
||||
let gm = geomMean(arr);
|
||||
let stdev = getStdev(arr);
|
||||
return stdev / gm;
|
||||
} else {
|
||||
return getStdev(arr) / avg(arr);
|
||||
}
|
||||
};
|
|
@ -1,27 +0,0 @@
|
|||
{
|
||||
"name": "utility-function-extractor",
|
||||
"version": "0.6.1",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"dev": "next dev",
|
||||
"build": "next build",
|
||||
"start": "next start"
|
||||
},
|
||||
"dependencies": {
|
||||
"axios": "^0.21.4",
|
||||
"d3": "^6.7.0",
|
||||
"next": "latest",
|
||||
"path": "^0.12.7",
|
||||
"react": "^17.0.1",
|
||||
"react-compound-slider": "^3.3.1",
|
||||
"react-dom": "^17.0.1",
|
||||
"react-markdown": "^6.0.2",
|
||||
"remark-gfm": "^1.0.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@netlify/plugin-nextjs": "^4.2.1",
|
||||
"autoprefixer": "^10.4.0",
|
||||
"postcss": "^8.4.4",
|
||||
"tailwindcss": "^2.2.19"
|
||||
}
|
||||
}
|
|
@ -1,9 +0,0 @@
|
|||
// import 'tailwindcss/tailwind.css'
|
||||
import 'tailwindcss/tailwind.css'
|
||||
import "../styles/globals.css";
|
||||
|
||||
function MyApp({ Component, pageProps }) {
|
||||
return <Component {...pageProps} />
|
||||
}
|
||||
|
||||
export default MyApp
|
|
@ -1,5 +0,0 @@
|
|||
// Next.js API route support: https://nextjs.org/docs/api-routes/introduction
|
||||
|
||||
export default function helloAPI(req, res) {
|
||||
res.status(200).json({ name: 'John Doe' })
|
||||
}
|
|
@ -1,32 +0,0 @@
|
|||
/* Notes */
|
||||
|
||||
// This function is just a simple wrapper around lib/comparisonView.
|
||||
// Most of the time, I'll want to edit that instead
|
||||
|
||||
/* Imports */
|
||||
import React from "react";
|
||||
import fs from "fs";
|
||||
import path from "path";
|
||||
import ComparisonView from "../lib/comparisonView.js";
|
||||
|
||||
/* Definitions */
|
||||
const elementsDocument = "../data/listOfMoralGoods.json";
|
||||
|
||||
/* React components */
|
||||
export async function getStaticProps() {
|
||||
const directory = path.join(process.cwd(), "pages");
|
||||
let listOfElementsForView = JSON.parse(
|
||||
fs.readFileSync(path.join(directory, elementsDocument), "utf8")
|
||||
);
|
||||
return {
|
||||
props: {
|
||||
listOfElementsForView,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
// Main react component
|
||||
export default function Home({ listOfElementsForView }) {
|
||||
return <ComparisonView listOfElementsForView={listOfElementsForView} />;
|
||||
}
|
||||
|
|
@ -1,31 +0,0 @@
|
|||
/* Notes */
|
||||
|
||||
// This function is just a simple wrapper around lib/comparisonView.
|
||||
// Most of the time, I'll want to edit that instead
|
||||
|
||||
/* Imports */
|
||||
import React from "react";
|
||||
import fs from "fs";
|
||||
import path from "path";
|
||||
import ComparisonView from "../lib/comparisonView.js";
|
||||
|
||||
/* Definitions */
|
||||
const elementsDocument = "../data/listOfOpenPhil2018AIRiskGrants.json";
|
||||
|
||||
/* React components */
|
||||
export async function getStaticProps() {
|
||||
const directory = path.join(process.cwd(), "pages");
|
||||
let listOfElementsForView = JSON.parse(
|
||||
fs.readFileSync(path.join(directory, elementsDocument), "utf8")
|
||||
);
|
||||
return {
|
||||
props: {
|
||||
listOfElementsForView,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
// Main react component
|
||||
export default function Home({ listOfElementsForView }) {
|
||||
return <ComparisonView listOfElementsForView={listOfElementsForView} />;
|
||||
}
|
|
@ -1,29 +0,0 @@
|
|||
/* Notes */
|
||||
|
||||
// This function is just a simple wrapper around lib/comparisonView.
|
||||
// Most of the time, I'll want to edit that instead
|
||||
|
||||
/* Imports */
|
||||
import React from "react";
|
||||
import fs from 'fs';
|
||||
import path from 'path';
|
||||
import ComparisonView from '../lib/comparisonView.js'
|
||||
|
||||
/* Definitions */
|
||||
const elementsDocument = '../data/listOfResearchOutputs.json'
|
||||
|
||||
/* React components */
|
||||
export async function getStaticProps() {
|
||||
const directory = path.join(process.cwd(), "pages")
|
||||
let listOfElementsForView = JSON.parse(fs.readFileSync(path.join(directory, elementsDocument), 'utf8'));
|
||||
return {
|
||||
props: {
|
||||
listOfElementsForView
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
// Main react component
|
||||
export default function Home({ listOfElementsForView }) {
|
||||
return(<ComparisonView listOfElementsForView={listOfElementsForView}/>)
|
||||
}
|
|
@ -1,7 +0,0 @@
|
|||
Copyright 2022 NUÑO SEMPERE
|
||||
|
||||
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.
|
|
@ -1,114 +0,0 @@
|
|||
## About
|
||||
|
||||
This repository creates a react webpage that allows to extract a utility function from possibly inconsistent binary comparisons.
|
||||
|
||||
It presents the users with a series of elements to compare, using merge-sort in the background to cleverly minimize the number of choices needed.
|
||||
|
||||
<p align="center">
|
||||
<img width="50%" height="50%" src="./public/example-prompt.png">
|
||||
</p>
|
||||
|
||||
Then, it cleverly aggregates them, on the one hand by producing a graphical representation:
|
||||
|
||||
<p align="center">
|
||||
<img width="50%" height="50%" src="./public/example-graph.png">
|
||||
</p>
|
||||
|
||||
and on the other hand doing some fast and clever mean aggregation [^1]:
|
||||
|
||||
<p align="center">
|
||||
<img width="50%" height="50%" src="./public/example-table.png">
|
||||
</p>
|
||||
|
||||
Initially, users could only input numbers, e.g., "A is `3` times better than B". But now, users can also input distributions, using the [squiggle](https://www.squiggle-language.com/) syntax, e.g., "A is `1 to 10` times better than B", or "A is `mm(normal(1, 10), uniform(0,100))` better than B".
|
||||
|
||||
**If you want to use the utility function extractor for a project, we are happy to add a page for your project, like `utility-function-extractor.quantifieduncertainty.org/your-project`**.
|
||||
|
||||
## Built with
|
||||
|
||||
- [Nextjs](https://nextjs.org/)
|
||||
- [Netlify](https://github.com/netlify/netlify-plugin-nextjs/#readme)
|
||||
- [React](https://reactjs.org/)
|
||||
- [Squiggle](https://www.squiggle-language.com/)
|
||||
- [Utility tools](https://github.com/quantified-uncertainty/utility-function-extractor/tree/master/packages/utility-tools)
|
||||
|
||||
## Usage
|
||||
|
||||
Navigate to [utility-function-extractor.quantifieduncertainty.org/](https://utility-function-extractor.quantifieduncertainty.org/), and start comparing objects.
|
||||
|
||||
You can change the list of objects to be compared by clicking on "advanced options".
|
||||
|
||||
After comparing objects for a while, you will get a table and a graph with results. You can also use the [utility tools](https://github.com/quantified-uncertainty/utility-function-extractor/tree/master/packages/utility-tools) package to process these results, for which you will need the json of comparisons, which can be found in "Advanced options" -> "Load comparisons"
|
||||
|
||||
## Notes
|
||||
|
||||
The core structure is json array of objects. Only the "name" attribute is required. If there is a "url", it is displayed nicely.
|
||||
|
||||
```
|
||||
[
|
||||
{
|
||||
"name": "Peter Parker",
|
||||
"someOptionalKey": "...",
|
||||
"anotherMoreOptionalKey": "...",
|
||||
},
|
||||
{
|
||||
"name": "Spiderman",
|
||||
"someOptionalKey": "...",
|
||||
"anotherMoreOptionalKey": "..."
|
||||
}
|
||||
]
|
||||
```
|
||||
|
||||
The core structure for links is as follows:
|
||||
|
||||
```
|
||||
[
|
||||
{
|
||||
"source": "Peter Parker",
|
||||
"target": "Spiderman",
|
||||
"squiggleString": "1 to 100",
|
||||
"distance": 26.639800977355474
|
||||
},
|
||||
{
|
||||
"source": "Spiderman",
|
||||
"target": "Jonah Jameson",
|
||||
"squiggleString": "20 to 2000",
|
||||
"distance": 6.76997149080232
|
||||
},
|
||||
|
||||
]
|
||||
```
|
||||
|
||||
A previous version of this webpage had a more complicated structure, but it has since been simplified.
|
||||
|
||||
## Contributions and help
|
||||
|
||||
We welcome PR requests.
|
||||
|
||||
## License
|
||||
|
||||
Distributed under the MIT License. See LICENSE.txt for more information.
|
||||
|
||||
## To do
|
||||
|
||||
- [x] Extract merge, findPath and aggregatePath functionality into different repos
|
||||
- [x] Send to mongo upon completion
|
||||
- [x] Push to github
|
||||
- [x] Push to netlify
|
||||
- [x] Don't allow further comparisons after completion
|
||||
- [x] Paths table
|
||||
- [x] Add paths table
|
||||
- [x] warn that the paths table is approximate.
|
||||
- I really don't feel like re-adding this after having worked out the distribution rather than the mean aggregation
|
||||
- On the other hand, I think it does make it more user to other users.
|
||||
- [x] Change README.
|
||||
- [ ] Add functionality like names, etc.
|
||||
- I also don't feel like doing this
|
||||
- [ ] Look back at Amazon thing which has been running
|
||||
- [ ] Simplify Graph and DynamicSquiggleChart components
|
||||
- [ ] Add squiggle component to initial comparison?
|
||||
- [ ] Understand why the rewrite doesn't
|
||||
- Maybe: When two elements are judged to be roughly equal
|
||||
- Maybe: Slightly different merge-sort algorithm.
|
||||
|
||||
[^1]: The program takes each element as a reference point in turn, and computing the possible distances from that reference point to all other points, and taking the geometric mean of these distances. This produces a number representing the value of each element, such that the ratios between elements represent the user's preferences: a utility function. However, this isn't perfect; the principled approach woud be to aggregate the distributions rather than their means. But this principled approach is much more slowly. For the principled approach, see the `utility-tools` repository.
|
|
@ -1,63 +0,0 @@
|
|||
import React, { useState } from "react";
|
||||
|
||||
export function ComparisonActuator({
|
||||
listOfElements,
|
||||
pairCurrentlyBeingCompared,
|
||||
moveToNextStep,
|
||||
isListOrdered,
|
||||
}) {
|
||||
const initialComparisonString = "";
|
||||
const [comparisonString, setComparisonString] = useState(
|
||||
initialComparisonString
|
||||
);
|
||||
const onChangeComparisonString = async (event) => {
|
||||
if (!isListOrdered) {
|
||||
await setComparisonString(event.target.value);
|
||||
}
|
||||
};
|
||||
|
||||
const onClickSubmitEvent = (event) => {
|
||||
if (!isListOrdered) {
|
||||
moveToNextStep({
|
||||
listOfElements,
|
||||
pairCurrentlyBeingCompared,
|
||||
comparisonString,
|
||||
});
|
||||
setComparisonString(initialComparisonString);
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="flex m-auto w-72">
|
||||
<div className="block m-auto text-center">
|
||||
<br />
|
||||
<label>
|
||||
{`... is `}
|
||||
<br />
|
||||
<input
|
||||
disabled={isListOrdered ? true : false}
|
||||
placeholder={"x to y"}
|
||||
type="text"
|
||||
className="text-center text-blueGray-600 bg-white rounded text-lg border-0 shadow outline-none focus:outline-none focus:ring w-8/12 h-10 m-2"
|
||||
value={comparisonString}
|
||||
onChange={onChangeComparisonString}
|
||||
/>
|
||||
<br />
|
||||
{`times as valuable as ...`}
|
||||
</label>
|
||||
<br />
|
||||
|
||||
<button
|
||||
className={
|
||||
!true
|
||||
? "bg-transparent hover:bg-blue-500 text-blue-700 font-semibold hover:text-white py-2 px-4 border border-blue-500 hover:border-transparent rounded mt-5"
|
||||
: "bg-transparent text-blue-700 font-semibold py-2 px-4 border border-blue-500 rounded mt-5"
|
||||
}
|
||||
onClick={onClickSubmitEvent}
|
||||
>
|
||||
Submit
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
|
@ -1,51 +0,0 @@
|
|||
import React from "react";
|
||||
|
||||
let capitalizeFirstLetter = (string) =>
|
||||
string.charAt(0).toUpperCase() + string.slice(1);
|
||||
|
||||
export function DisplayElementForComparison({ element }) {
|
||||
let otherkeys = Object.keys(element).filter(
|
||||
(key) =>
|
||||
key != "name" && key != "url" && key != "id" && key != "isReferenceValue"
|
||||
);
|
||||
let othervalues = otherkeys.map((key) => element[key]);
|
||||
let otherpairs = otherkeys.map((key, i) => ({
|
||||
key: capitalizeFirstLetter(key),
|
||||
value: othervalues[i],
|
||||
}));
|
||||
|
||||
if (element.url) {
|
||||
return (
|
||||
<div className="flex m-auto border-gray-300 border-4 h-72 w-72 p-5">
|
||||
<div className="block m-auto text-center">
|
||||
<div>
|
||||
{/*<a href={element.url} target="_blank">*/}
|
||||
<h2>{`${element.name}`}</h2>
|
||||
{/*</a>*/}
|
||||
{otherpairs.map((pair) => (
|
||||
<p key={pair.value}>{`${pair.key}: ${pair.value}`}</p>
|
||||
))}
|
||||
<p>
|
||||
<a href={element.url} target="_blank">
|
||||
More info
|
||||
</a>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
} else {
|
||||
return (
|
||||
<div className="flex m-auto border-gray-300 border-4 h-72 w-72 p-5">
|
||||
<div className="block m-auto text-center">
|
||||
<div>
|
||||
<h2>{`${element.name}`}</h2>
|
||||
{otherpairs.map((pair) => (
|
||||
<p key={pair.value}>{`${pair.key}: ${pair.value}`}</p>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
|
@ -1,260 +0,0 @@
|
|||
import React, { useEffect, useState, useRef } from "react";
|
||||
import colormap from "colormap";
|
||||
import cytoscape from "cytoscape";
|
||||
|
||||
import { DynamicSquiggleChart } from "../dynamicSquiggleChart.js";
|
||||
import {
|
||||
resolveToNumIfPossible,
|
||||
getSquiggleSparkline,
|
||||
} from "../../lib/squiggleCalculations.js";
|
||||
import { truncateValueForDisplay } from "../../lib/truncateNums.js";
|
||||
import { cutOffLongNames } from "../../lib/stringManipulations.js";
|
||||
|
||||
// import spread from "cytoscape-spread";
|
||||
// import dagre from "cytoscape-dagre";
|
||||
// import cola from "cytoscape-cola";
|
||||
// import fcose from "cytoscape-fcose";
|
||||
// import avsdf from "cytoscape-avsdf";
|
||||
|
||||
const effectButtonStyle =
|
||||
"bg-transparent m-2 hover:bg-blue-500 text-blue-700 font-semibold hover:text-white py-2 px-4 border border-blue-500 hover:border-transparent rounded mt-5";
|
||||
|
||||
const getEdgeLabel = async (squiggleString) => {
|
||||
let sparkline = await getSquiggleSparkline(squiggleString);
|
||||
let num = await resolveToNumIfPossible(squiggleString);
|
||||
|
||||
let sparklineConcat = "";
|
||||
if (false && sparkline.success) {
|
||||
console.log(sparkline);
|
||||
|
||||
sparklineConcat =
|
||||
sparklineConcat + " →" + sparkline.sparkline.replace("▁▁▁▁▁▁▁▁▁▁▁▁▁", "");
|
||||
//alert("▁▁▁▁▁▁▁▁▁▁▁");
|
||||
}
|
||||
if (num.asNum) {
|
||||
sparklineConcat =
|
||||
sparklineConcat + " ⇾ " + truncateValueForDisplay(num.num);
|
||||
//alert("▁▁▁▁▁▁▁▁▁▁▁");
|
||||
}
|
||||
|
||||
return squiggleString + sparklineConcat;
|
||||
};
|
||||
|
||||
const getColors = (n) => {
|
||||
let colors;
|
||||
if (n >= 9) {
|
||||
colors = colormap({
|
||||
colormap: "viridis",
|
||||
nshades: n,
|
||||
format: "hex",
|
||||
alpha: 1,
|
||||
});
|
||||
} else {
|
||||
colors = colormap({
|
||||
colormap: "greys", // other themes: hot, winter, etc.
|
||||
nshades: n,
|
||||
format: "hex",
|
||||
alpha: 1,
|
||||
});
|
||||
}
|
||||
return colors;
|
||||
};
|
||||
|
||||
export function Graph({
|
||||
listOfElements,
|
||||
links,
|
||||
isListOrdered,
|
||||
listAfterMergeSort,
|
||||
}) {
|
||||
const containerRef = useRef("hello-world");
|
||||
const [visibility, setVisibility] = useState(""); /// useState("invisible");
|
||||
const [cs, setCs] = useState(null); /// useState("invisible");
|
||||
const [selectedLink, setSelectedLink] = useState(null);
|
||||
const [selectedLinkTimeout, setSelectedLinkTimeout] = useState(null);
|
||||
|
||||
const callEffect = async ({
|
||||
listOfElements,
|
||||
links,
|
||||
isListOrdered,
|
||||
listAfterMergeSort,
|
||||
}) => {
|
||||
//setVisibility("invisible");
|
||||
let layoutName = "circle"; //
|
||||
|
||||
// cytoscape.use(spread); // necessary for non-default themes,
|
||||
let listOfElementsForGraph = isListOrdered
|
||||
? listAfterMergeSort
|
||||
: listOfElements;
|
||||
|
||||
let colors = new Array(listOfElements.length);
|
||||
if (isListOrdered) {
|
||||
colors = getColors(listOfElements.length);
|
||||
}
|
||||
|
||||
let nodeElements = listOfElements.map((element, i) => {
|
||||
return {
|
||||
data: {
|
||||
id: cutOffLongNames(element.name),
|
||||
color: colors[i] || "darkgreen",
|
||||
labelColor: isListOrdered
|
||||
? i >= listOfElementsForGraph.length - 2
|
||||
? "black"
|
||||
: "white"
|
||||
: "white",
|
||||
},
|
||||
};
|
||||
});
|
||||
let linkElements = await Promise.all(
|
||||
links.map(async (link, i) => {
|
||||
return {
|
||||
data: {
|
||||
id: `link-${i}`,
|
||||
source: cutOffLongNames(link.source),
|
||||
target: cutOffLongNames(link.target),
|
||||
label: await getEdgeLabel(link.squiggleString),
|
||||
squiggleString: link.squiggleString,
|
||||
},
|
||||
};
|
||||
})
|
||||
);
|
||||
|
||||
const cytoscapeStylesheet = [
|
||||
{
|
||||
selector: "node",
|
||||
style: {
|
||||
padding: "30px",
|
||||
shape: "round-rectangle",
|
||||
content: "data(id)",
|
||||
"background-color": "data(color)",
|
||||
"text-wrap": "wrap",
|
||||
"text-max-width": 70,
|
||||
"z-index": 1,
|
||||
},
|
||||
},
|
||||
{
|
||||
selector: "node[id]",
|
||||
style: {
|
||||
label: "data(id)",
|
||||
"font-size": "13",
|
||||
color: "data(labelColor)",
|
||||
"text-halign": "center",
|
||||
"text-valign": "center",
|
||||
"z-index": 1,
|
||||
},
|
||||
},
|
||||
{
|
||||
selector: "edge",
|
||||
style: {
|
||||
"curve-style": "unbundled-bezier",
|
||||
"target-arrow-shape": "vee",
|
||||
width: 1.5,
|
||||
"target-arrow-color": "green",
|
||||
"arrow-scale": 3,
|
||||
"target-arrow-fill": "filled",
|
||||
"text-rotation": "autorotate",
|
||||
"z-index": 0,
|
||||
},
|
||||
},
|
||||
{
|
||||
selector: "edge[label]",
|
||||
style: {
|
||||
label: "data(label)",
|
||||
"font-size": "12",
|
||||
|
||||
"text-background-color": "#f9f9f9",
|
||||
"text-background-opacity": 1,
|
||||
"text-background-padding": "4px",
|
||||
|
||||
"text-border-color": "black",
|
||||
"text-border-style": "solid",
|
||||
"text-border-width": 0.5,
|
||||
"text-border-opacity": 1,
|
||||
"z-index": 3,
|
||||
},
|
||||
},
|
||||
];
|
||||
|
||||
const config = {
|
||||
container: containerRef.current,
|
||||
style: cytoscapeStylesheet,
|
||||
elements: [...nodeElements, ...linkElements],
|
||||
layout: {
|
||||
name: layoutName, // circle, grid, dagre
|
||||
minDist: 10,
|
||||
//prelayout: false,
|
||||
// animate: false, // whether to transition the node positions
|
||||
// animationDuration: 250, // duration of animation in ms if enabled
|
||||
// the cytoscape documentation is pretty good here.
|
||||
},
|
||||
userZoomingEnabled: false,
|
||||
userPanningEnabled: false,
|
||||
};
|
||||
let newCs = cytoscape(config);
|
||||
setCs(newCs);
|
||||
// setTimeout(() => setVisibility(""), 700);
|
||||
// necessary for themes like spread, which have
|
||||
// a confusing animation at the beginning
|
||||
};
|
||||
useEffect(() => {
|
||||
callEffect({
|
||||
listOfElements,
|
||||
links,
|
||||
isListOrdered,
|
||||
listAfterMergeSort,
|
||||
});
|
||||
}, [listOfElements, links, isListOrdered, listAfterMergeSort, selectedLink]);
|
||||
|
||||
useEffect(() => {
|
||||
if (cs != null) {
|
||||
clearTimeout(selectedLinkTimeout);
|
||||
let newTimeout = setTimeout(() => {
|
||||
cs.edges().on("mouseover", (event) => {
|
||||
// on("click",
|
||||
let edge = event.target;
|
||||
// alert(JSON.stringify(edge.json()));
|
||||
console.log(JSON.stringify(edge.json()));
|
||||
setSelectedLink(JSON.parse(JSON.stringify(edge.json())).data);
|
||||
});
|
||||
}, 100);
|
||||
setSelectedLinkTimeout(newTimeout);
|
||||
}
|
||||
}, [cs]);
|
||||
return (
|
||||
<div className="grid place-items-center">
|
||||
<div
|
||||
className={
|
||||
visibility +
|
||||
`grid grid-cols-${
|
||||
selectedLink == null ? "1 " : "2"
|
||||
} place-items-center place-self-center space-x-0 w-10/12 `
|
||||
}
|
||||
>
|
||||
<div
|
||||
ref={containerRef}
|
||||
style={{
|
||||
height: "900px", // isListOrdered ? "900px" : "500px",
|
||||
width: "900px", // isListOrdered ? "900px" : "500px",
|
||||
}}
|
||||
className=""
|
||||
/>
|
||||
<DynamicSquiggleChart
|
||||
link={selectedLink}
|
||||
stopShowing={() => setSelectedLink(null)}
|
||||
/>
|
||||
</div>
|
||||
<button
|
||||
className={effectButtonStyle}
|
||||
onClick={() =>
|
||||
callEffect({
|
||||
listOfElements,
|
||||
links,
|
||||
isListOrdered,
|
||||
listAfterMergeSort,
|
||||
})
|
||||
}
|
||||
>
|
||||
{"Redraw graph"}
|
||||
</button>
|
||||
</div>
|
||||
);
|
||||
}
|
|
@ -1,171 +0,0 @@
|
|||
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 { Separator } from "./separator.js";
|
||||
import { ResultsTable } from "./resultsTable.js";
|
||||
|
||||
import { AdvancedOptions } from "./advancedOptions/advancedOptions.js";
|
||||
import { Graph } from "./graph/graph.js";
|
||||
import { pushToMongo } from "../lib/pushToMongo.js";
|
||||
import { resolveToNumIfPossible } from "../lib/squiggleCalculations.js";
|
||||
|
||||
export function Homepage({ listOfElementsInit }) {
|
||||
const SLICE = false;
|
||||
|
||||
/* Statefull elements */
|
||||
|
||||
// list of elements
|
||||
const [listOfElements, setListOfElements] = useState(
|
||||
SLICE ? listOfElementsInit.slice(0, 4) : listOfElementsInit
|
||||
);
|
||||
|
||||
// number of steps
|
||||
const numStepsInit = 0;
|
||||
const [numStepsNow, setNumStepsNow] = useState(numStepsInit);
|
||||
|
||||
// is list ordered?
|
||||
const [isListOrdered, setIsListOrdered] = useState(false);
|
||||
const [listAfterMergeSort, setListAfterMergeSort] = useState([]);
|
||||
|
||||
// list of comparisons
|
||||
const [links, setLinks] = useState([]);
|
||||
const addLink = (link, links) => setLinks([...links, link]);
|
||||
|
||||
// paired being currently compared
|
||||
const pairCurrentlyBeingComparedInit = [
|
||||
listOfElementsInit[0],
|
||||
listOfElementsInit[1],
|
||||
];
|
||||
const [pairCurrentlyBeingCompared, setPairCurrentlyBeingCompared] = useState(
|
||||
pairCurrentlyBeingComparedInit
|
||||
);
|
||||
|
||||
/* Effects */
|
||||
|
||||
// dataset changer
|
||||
const onChangeOfDataset = (newListOfElements) => {
|
||||
setListOfElements(newListOfElements);
|
||||
setLinks([]);
|
||||
setPairCurrentlyBeingCompared([newListOfElements[0], newListOfElements[1]]);
|
||||
setNumStepsNow(0);
|
||||
setIsListOrdered(false);
|
||||
setListAfterMergeSort([]);
|
||||
};
|
||||
|
||||
// process next step
|
||||
const mergeSortStep = ({ list, links }) => {
|
||||
let mergeSortOutput = mergeSort({
|
||||
list: list,
|
||||
links: links,
|
||||
});
|
||||
setNumStepsNow(numStepsNow + 1);
|
||||
if (mergeSortOutput.finishedOrderingList == false) {
|
||||
let newPairToCompare = mergeSortOutput.uncomparedElements;
|
||||
setIsListOrdered(false);
|
||||
setPairCurrentlyBeingCompared(newPairToCompare);
|
||||
} else {
|
||||
setListAfterMergeSort(mergeSortOutput.orderedList);
|
||||
pushToMongo({ mergeSortOutput, links });
|
||||
setIsListOrdered(true); // should be at the end, because some useEffects are triggered by it.
|
||||
}
|
||||
};
|
||||
|
||||
// Main mergesort step
|
||||
const moveToNextStep = async ({
|
||||
listOfElements,
|
||||
pairCurrentlyBeingCompared,
|
||||
comparisonString,
|
||||
whileChangingStuff,
|
||||
newLinksFromChangingStuff,
|
||||
}) => {
|
||||
if (!whileChangingStuff) {
|
||||
// In the normal course of things:
|
||||
let newLink = {
|
||||
source: pairCurrentlyBeingCompared[0].name,
|
||||
target: pairCurrentlyBeingCompared[1].name,
|
||||
squiggleString: comparisonString,
|
||||
};
|
||||
|
||||
let numOption = await resolveToNumIfPossible(comparisonString);
|
||||
if (numOption.asNum == false) {
|
||||
alert(JSON.stringify(numOption.errorMsg));
|
||||
} else if (numOption.asNum == true) {
|
||||
newLink = { ...newLink, distance: numOption.num };
|
||||
addLink(newLink, links);
|
||||
let newLinks = [...links, newLink];
|
||||
console.log("links: ", links);
|
||||
mergeSortStep({ list: listOfElements, links: newLinks });
|
||||
}
|
||||
} else {
|
||||
// When changing comparisons:
|
||||
mergeSortStep({
|
||||
list: listOfElements,
|
||||
links: newLinksFromChangingStuff,
|
||||
});
|
||||
setNumStepsNow(0); // almost no guarantees of how many left.
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="block w-full items-center sm:w-full mt-10">
|
||||
<Title />
|
||||
|
||||
<ProgressIndicator
|
||||
numStepsNow={numStepsNow}
|
||||
numElements={listOfElements.length}
|
||||
/>
|
||||
|
||||
{/* Comparisons section */}
|
||||
<div
|
||||
className={"grid place-items-center" /*isListOrdered ? "hidden" : ""*/}
|
||||
>
|
||||
<div className="grid grid-rows-1 grid-cols-3 place-items-center w-6/11 mt-10">
|
||||
<DisplayElementForComparison
|
||||
element={pairCurrentlyBeingCompared[0]}
|
||||
></DisplayElementForComparison>
|
||||
|
||||
<ComparisonActuator
|
||||
listOfElements={listOfElements}
|
||||
pairCurrentlyBeingCompared={pairCurrentlyBeingCompared}
|
||||
moveToNextStep={moveToNextStep}
|
||||
isListOrdered={isListOrdered}
|
||||
/>
|
||||
|
||||
<DisplayElementForComparison
|
||||
element={pairCurrentlyBeingCompared[1]}
|
||||
></DisplayElementForComparison>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* <Results table /> */}
|
||||
<ResultsTable
|
||||
isListOrdered={isListOrdered}
|
||||
listAfterMergeSort={listAfterMergeSort}
|
||||
links={links}
|
||||
/>
|
||||
|
||||
{/* <Graph /> */}
|
||||
<Separator />
|
||||
<Graph
|
||||
listOfElements={listOfElements}
|
||||
links={links}
|
||||
isListOrdered={isListOrdered}
|
||||
listAfterMergeSort={listAfterMergeSort}
|
||||
/>
|
||||
|
||||
{/* Advanced options section */}
|
||||
<Separator />
|
||||
<AdvancedOptions
|
||||
links={links}
|
||||
setLinks={setLinks}
|
||||
listOfElements={listOfElements}
|
||||
moveToNextStep={moveToNextStep}
|
||||
onChangeOfDataset={onChangeOfDataset}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
|
@ -1,48 +0,0 @@
|
|||
import React, { useState } from "react";
|
||||
|
||||
function expectedNumMergeSortSteps(n) {
|
||||
// https://cs.stackexchange.com/questions/82862/expected-number-of-comparisons-in-a-merge-step
|
||||
// n-2 for each step, so (n-2) + (n-2)/2 + (n-2)/4 + ...
|
||||
// ~ 2*(n-2) -1 = 2*n - 3
|
||||
if (n == 0) {
|
||||
return 0;
|
||||
} else if (n == 1) {
|
||||
return 0;
|
||||
} else if (n == 2) {
|
||||
return 1;
|
||||
} else if (n == 3) {
|
||||
return 2;
|
||||
} else {
|
||||
return (
|
||||
Math.ceil(n ** 2 / (n + 2)) + expectedNumMergeSortSteps(Math.ceil(n / 2))
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
const firstFewMaxMergeSortSequence = [
|
||||
0, 0, 1, 3, 5, 8, 11, 14, 17, 21, 25, 29, 33, 37, 41, 45, 49, 54, 59, 64, 69,
|
||||
74, 79, 84, 89, 94, 99, 104, 109, 114, 119, 124, 129, 135, 141, 147, 153, 159,
|
||||
165, 171, 177, 183, 189, 195, 201, 207, 213, 219, 225, 231, 237, 243, 249,
|
||||
255, 261, 267, 273, 279, 285,
|
||||
];
|
||||
|
||||
function maxMergeSortSteps(n) {
|
||||
if (n < firstFewMaxMergeSortSequence.length) {
|
||||
return firstFewMaxMergeSortSequence[n];
|
||||
} else {
|
||||
return (
|
||||
maxMergeSortSteps(Math.floor(n / 2)) +
|
||||
maxMergeSortSteps(Math.ceil(n / 2)) +
|
||||
n -
|
||||
1
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export function ProgressIndicator({ numStepsNow, numElements }) {
|
||||
const expectedNumSteps = expectedNumMergeSortSteps(numElements);
|
||||
const maxSteps = maxMergeSortSteps(numElements);
|
||||
return (
|
||||
<p>{`${numStepsNow} out of ~${expectedNumSteps} (max ${maxSteps}) comparisons`}</p>
|
||||
);
|
||||
}
|
|
@ -1,140 +0,0 @@
|
|||
import React, { useState, useEffect } from "react";
|
||||
import { findDistances, aggregatePaths } from "utility-tools";
|
||||
|
||||
import { Separator } from "./separator.js";
|
||||
|
||||
import { truncateValueForDisplay } from "../lib/truncateNums.js";
|
||||
import { cutOffLongNames } from "../lib/stringManipulations.js";
|
||||
import { getCoefficientOfVariation } from "../lib/coefficientOfVariation.js";
|
||||
|
||||
async function fullResultsTable({ listAfterMergeSort, links }) {
|
||||
console.log("listAfterMergeSort", listAfterMergeSort);
|
||||
console.log(links);
|
||||
let pathsArray = await findDistances({
|
||||
orderedList: listAfterMergeSort,
|
||||
links: links,
|
||||
});
|
||||
let aggregatedPaths = await aggregatePaths({
|
||||
pathsArray: pathsArray,
|
||||
orderedList: listAfterMergeSort,
|
||||
aggregationType: "mean",
|
||||
// VERBOSE: false,
|
||||
});
|
||||
return aggregatedPaths;
|
||||
}
|
||||
|
||||
function abridgeArrayAndDisplay(array) {
|
||||
let newArray;
|
||||
let formatForDisplay;
|
||||
if (array.length > 10) {
|
||||
newArray = array.slice(0, 9);
|
||||
formatForDisplay = newArray.map((d) => truncateValueForDisplay(d));
|
||||
formatForDisplay[9] = "...";
|
||||
} else {
|
||||
newArray = array;
|
||||
formatForDisplay = newArray.map((d) => truncateValueForDisplay(d));
|
||||
}
|
||||
let result = JSON.stringify(formatForDisplay, null, 2).replaceAll(`"`, "");
|
||||
return result;
|
||||
}
|
||||
|
||||
function getRow(row, i) {
|
||||
return (
|
||||
<tr
|
||||
className="border-b dark:bg-gray-800 dark:border-gray-700 odd:bg-white even:bg-gray-50 odd:dark:bg-gray-800 even:dark:bg-gray-700"
|
||||
key={`row-display-${i}`}
|
||||
>
|
||||
<td className="px-6 py-4 pt-7">{i}</td>
|
||||
<td className="px-6 py-4">{cutOffLongNames(row.name)}</td>
|
||||
<td className="text-center px-6 py-4">
|
||||
{abridgeArrayAndDisplay(row.arrayMeans)}
|
||||
</td>
|
||||
<td className="text-center px-6 py-4">
|
||||
{truncateValueForDisplay(row.aggregatedMeans)}
|
||||
</td>
|
||||
<td className="text-center px-6 py-4">
|
||||
{truncateValueForDisplay(getCoefficientOfVariation(row.arrayMeans))}
|
||||
</td>
|
||||
</tr>
|
||||
);
|
||||
}
|
||||
|
||||
function reactTableContents(tableContents) {
|
||||
return tableContents.map((row, i) => getRow(row, i));
|
||||
}
|
||||
|
||||
export function ResultsTable({ isListOrdered, listAfterMergeSort, links }) {
|
||||
const [isTableComputed, setIsTableComputed] = useState(false);
|
||||
const [tableContents, setTableContents] = useState([]);
|
||||
|
||||
useEffect(() => {
|
||||
let iAsync = async () => {
|
||||
if (isListOrdered && listAfterMergeSort.length > 0) {
|
||||
// both comparisons aren't strictly necessary,
|
||||
// but it bit me once, so I'm leaving it
|
||||
let tableContentsResult = await fullResultsTable({
|
||||
listAfterMergeSort,
|
||||
links,
|
||||
});
|
||||
console.log(tableContentsResult);
|
||||
setTableContents(tableContentsResult);
|
||||
setIsTableComputed(true);
|
||||
}
|
||||
return () => console.log("cleanup");
|
||||
};
|
||||
iAsync();
|
||||
}, [isListOrdered, listAfterMergeSort, links]);
|
||||
|
||||
return !(isListOrdered && isTableComputed) ? (
|
||||
""
|
||||
) : (
|
||||
<div>
|
||||
<div>
|
||||
<Separator />
|
||||
<div className="relative overflow-x-auto shadow-md sm:rounded-lg mt-10">
|
||||
<table className="w-full text-sm text-left text-gray-800 dark:text-gray-400">
|
||||
<thead className=" text-xs text-gray-700 bg-gray-50 dark:bg-gray-700 dark:text-gray-400">
|
||||
<tr>
|
||||
<th scope="col" className="px-6 py-3">
|
||||
Position
|
||||
</th>
|
||||
|
||||
<th scope="col" className="px-6 py-3">
|
||||
Element
|
||||
</th>
|
||||
|
||||
<th scope="col" className="text-center px-6 py-3">
|
||||
Possible relative values
|
||||
</th>
|
||||
|
||||
<th scope="col" className="text-center px-6 py-3">
|
||||
Aggregated Means*
|
||||
</th>
|
||||
<th scope="col" className="text-center px-6 py-3">
|
||||
Coefficient of variation
|
||||
</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>{reactTableContents(tableContents)}</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
<div className="grid w-full place-items-center text-center ">
|
||||
<p className="mt-8 max-w-5xl">
|
||||
*This is the geometric mean of all means of paths if all elements are
|
||||
either all positive or all negative, and the arithmetic mean
|
||||
otherwise. Paths with a non-numeric mean (e.g., resulting from
|
||||
dividing by a mean of 0) are ignored. For a principled aggregation
|
||||
which is able to produce meaningfull 90% confidence intervals, see the{" "}
|
||||
<a
|
||||
href="https://github.com/quantified-uncertainty/utility-function-extractor/tree/master/packages/utility-tools"
|
||||
target="_blank"
|
||||
>
|
||||
utility-tools package
|
||||
</a>{" "}
|
||||
in npm or Github
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
|
@ -1,9 +0,0 @@
|
|||
import React from "react";
|
||||
|
||||
export function Separator() {
|
||||
return (
|
||||
<div className="py-4">
|
||||
<div className="w-full border-t border-4 border-gray-300 mt-10"></div>
|
||||
</div>
|
||||
);
|
||||
}
|
|
@ -1,5 +0,0 @@
|
|||
import React, { useState } from "react";
|
||||
|
||||
export function Title() {
|
||||
return <h1 className="text-6xl font-bold ">Utility Function Extractor</h1>;
|
||||
}
|
|
@ -1,37 +0,0 @@
|
|||
[
|
||||
{
|
||||
"name": "Doubling consumption for one person for one year",
|
||||
"note": "at fairly low levels of wealth",
|
||||
"isReferenceValue": true,
|
||||
"url": "https://docs.google.com/spreadsheets/d/11HsJLpq0Suf3SK_PmzzWpK1tr_BTd364j0l3xVvSCQw/edit#gid=1362437801&range=A5:E5"
|
||||
},
|
||||
{
|
||||
"name": "Averting the death of an individual under 5 from malaria",
|
||||
"url": "https://docs.google.com/spreadsheets/d/11HsJLpq0Suf3SK_PmzzWpK1tr_BTd364j0l3xVvSCQw/edit#gid=1362437801&range=A8:T8"
|
||||
},
|
||||
{
|
||||
"name": "Averting the death of an individual 5 or older from malaria",
|
||||
"url": "https://docs.google.com/spreadsheets/d/11HsJLpq0Suf3SK_PmzzWpK1tr_BTd364j0l3xVvSCQw/edit#gid=1362437801&range=A9:T9"
|
||||
},
|
||||
{
|
||||
"name": "Averting the death of a 6- to 59-month-old child",
|
||||
"note": "through Vitamin A Supplementation",
|
||||
"url": "https://docs.google.com/spreadsheets/d/11HsJLpq0Suf3SK_PmzzWpK1tr_BTd364j0l3xVvSCQw/edit#gid=1362437801&range=A10:T10"
|
||||
},
|
||||
{
|
||||
"name": "Averting the death of an individual under 5 from vaccine-preventable diseases",
|
||||
"url": "https://docs.google.com/spreadsheets/d/11HsJLpq0Suf3SK_PmzzWpK1tr_BTd364j0l3xVvSCQw/edit#gid=1362437801&range=A11:T11"
|
||||
},
|
||||
{
|
||||
"name": "Averting the death of an individual 5-14 years old from vaccine-preventable diseases",
|
||||
"url": "https://docs.google.com/spreadsheets/d/11HsJLpq0Suf3SK_PmzzWpK1tr_BTd364j0l3xVvSCQw/edit#gid=1362437801&range=A12:T12"
|
||||
},
|
||||
{
|
||||
"name": "Averting the death of an individual 15-49 years old from vaccine-preventable diseases",
|
||||
"url": "https://docs.google.com/spreadsheets/d/11HsJLpq0Suf3SK_PmzzWpK1tr_BTd364j0l3xVvSCQw/edit#gid=1362437801&range=A13:T13"
|
||||
},
|
||||
{
|
||||
"name": "Averting the death of an individual 50-74 years old from vaccine-preventable diseases",
|
||||
"url": "https://docs.google.com/spreadsheets/d/11HsJLpq0Suf3SK_PmzzWpK1tr_BTd364j0l3xVvSCQw/edit#gid=1362437801&range=A14:T14"
|
||||
}
|
||||
]
|
|
@ -1,47 +0,0 @@
|
|||
[
|
||||
{
|
||||
"name": "Michael Cohen and Dmitrii Krasheninnikov — Scholarship Support (2018)",
|
||||
"url": "https://docs.google.com/document/d/1VlN6I4Jauarx-0Fp7AC1ggeQ02AITsN7S56ffAO9NTU/edit#heading=h.jnlrsr63yliq",
|
||||
"amount": "$159k"
|
||||
},
|
||||
{
|
||||
"name": "AI Impacts — General Support (2018)",
|
||||
"url": "https://docs.google.com/document/d/1VlN6I4Jauarx-0Fp7AC1ggeQ02AITsN7S56ffAO9NTU/edit#heading=h.6m6tebpouzt1",
|
||||
"amount": "$100k"
|
||||
},
|
||||
{
|
||||
"name": "Oxford University — Research on the Global Politics of AI",
|
||||
"url": "https://docs.google.com/document/d/1VlN6I4Jauarx-0Fp7AC1ggeQ02AITsN7S56ffAO9NTU/edit#heading=h.c6r2m7i749ay",
|
||||
"amount": "$429k"
|
||||
},
|
||||
{
|
||||
"name": "Ought — General Support (2018)",
|
||||
"url": "https://docs.google.com/document/d/1VlN6I4Jauarx-0Fp7AC1ggeQ02AITsN7S56ffAO9NTU/edit#heading=h.xnzaj48k3fdb",
|
||||
"amount": "$525k"
|
||||
},
|
||||
{
|
||||
"name": "Machine Intelligence Research Institute — AI Safety Retraining Program",
|
||||
"url": "https://docs.google.com/document/d/1VlN6I4Jauarx-0Fp7AC1ggeQ02AITsN7S56ffAO9NTU/edit#heading=h.h922w7eh5rq6",
|
||||
"amount": "$150k"
|
||||
},
|
||||
{
|
||||
"name": "UC Berkeley — AI Safety Research (2018)",
|
||||
"url": "https://docs.google.com/document/d/1VlN6I4Jauarx-0Fp7AC1ggeQ02AITsN7S56ffAO9NTU/edit#heading=h.rrsbecbboed8",
|
||||
"amount": "$1.145M"
|
||||
},
|
||||
{
|
||||
"name": "Open Phil AI Fellowship — 2018 Class",
|
||||
"url": "https://docs.google.com/document/d/1VlN6I4Jauarx-0Fp7AC1ggeQ02AITsN7S56ffAO9NTU/edit#heading=h.p8xd58asz6a2",
|
||||
"amount": "$1.135M"
|
||||
},
|
||||
{
|
||||
"name": "Wilson Center — AI Policy Seminar Series",
|
||||
"url": "https://docs.google.com/document/d/1VlN6I4Jauarx-0Fp7AC1ggeQ02AITsN7S56ffAO9NTU/edit#heading=h.qiurhycylgi3",
|
||||
"amount": "$400k"
|
||||
},
|
||||
{
|
||||
"name": "Stanford University — Machine Learning Security Research Led by Dan Boneh and Florian Tramer",
|
||||
"url": "https://docs.google.com/document/d/1VlN6I4Jauarx-0Fp7AC1ggeQ02AITsN7S56ffAO9NTU/edit#heading=h.ox8adhpgba86",
|
||||
"amount": "$100k"
|
||||
}
|
||||
]
|
|
@ -1,63 +0,0 @@
|
|||
[
|
||||
{
|
||||
"name": "A comment on setting up a charity",
|
||||
"url": "https://forum.effectivealtruism.org/posts/3PjNiLLkCMzAN2BSz/when-setting-up-a-charity-should-you-employ-a-lawyer?commentId=YNKNcp6nKqxqkZgCu"
|
||||
},
|
||||
{
|
||||
"name": "Center for Election Science EA Wiki stub",
|
||||
"url": "https://forum.effectivealtruism.org/tag/center-for-election-science"
|
||||
},
|
||||
{
|
||||
"name": "Extinguishing or preventing coal seam fires is a potential cause area",
|
||||
"url": "https://forum.effectivealtruism.org/posts/2nrx8GdtobScoAZF8/extinguishing-or-preventing-coal-seam-fires-is-a-potential"
|
||||
},
|
||||
{
|
||||
"name": "What are some low-information priors that you find practically useful for thinking about the world?",
|
||||
"url": "https://forum.effectivealtruism.org/posts/SBbwzovWbghLJixPn/what-are-some-low-information-priors-that-you-find"
|
||||
},
|
||||
{
|
||||
"name": "Database of orgs relevant to longtermist/x-risk work",
|
||||
"url": "https://forum.effectivealtruism.org/posts/twMs8xsgwnYvaowWX/database-of-orgs-relevant-to-longtermist-x-risk-work"
|
||||
},
|
||||
{
|
||||
"name": "Reversals in Psychology",
|
||||
"url": "https://www.gleech.org/psych"
|
||||
},
|
||||
{
|
||||
"name": "A Model of Patient Spending and Movement Building",
|
||||
"url": "https://forum.effectivealtruism.org/posts/FXPaccMDPaEZNyyre/a-model-of-patient-spending-and-movement-building"
|
||||
},
|
||||
{
|
||||
"name": "Shallow evaluations of longtermist organizations",
|
||||
"url": "https://forum.effectivealtruism.org/posts/xmmqDdGqNZq5RELer/shallow-evaluations-of-longtermist-organizations"
|
||||
},
|
||||
{
|
||||
"name": "The motivated reasoning critique of effective altruism",
|
||||
"url": "https://forum.effectivealtruism.org/posts/pxALB46SEkwNbfiNS/the-motivated-reasoning-critique-of-effective-altruism"
|
||||
},
|
||||
{
|
||||
"name": "Categorizing Variants of Goodhart's Law",
|
||||
"url": "https://arxiv.org/abs/1803.04585",
|
||||
"isReferenceValue": true
|
||||
},
|
||||
{
|
||||
"name": "The Vulnerable World Hypothesis",
|
||||
"url": "https://nickbostrom.com/papers/vulnerable.pdf"
|
||||
},
|
||||
{
|
||||
"name": "The Global Priorities Institute's Research Agenda",
|
||||
"url": "https://globalprioritiesinstitute.org/research-agenda/"
|
||||
},
|
||||
{
|
||||
"name": "Superintelligence",
|
||||
"url": "https://en.wikipedia.org/wiki/Superintelligence%3A_Paths%2C_Dangers%2C_Strategies"
|
||||
},
|
||||
{
|
||||
"name": "Thinking Fast and Slow",
|
||||
"url": "https://en.wikipedia.org/wiki/Thinking%2C_Fast_and_Slow"
|
||||
},
|
||||
{
|
||||
"name": "The Mathematical Theory of Communication",
|
||||
"url": "https://en.wikipedia.org/wiki/A_Mathematical_Theory_of_Communication"
|
||||
}
|
||||
]
|
|
@ -1,483 +0,0 @@
|
|||
[
|
||||
|
||||
{
|
||||
|
||||
"source": "Thinking Fast and Slow",
|
||||
|
||||
"target": "The Mathematical Theory of Communication",
|
||||
|
||||
"distance": 5,
|
||||
|
||||
"reasoning": "Seems like both sets of ideas would've happened eventually, my guess is that information theory was more important and counterfactual sped up by more"
|
||||
|
||||
},
|
||||
|
||||
{
|
||||
|
||||
"source": "The Global Priorities Institute's Research Agenda",
|
||||
|
||||
"target": "Superintelligence",
|
||||
|
||||
"distance": 20,
|
||||
|
||||
"reasoning": ""
|
||||
|
||||
},
|
||||
|
||||
{
|
||||
|
||||
"source": "The Global Priorities Institute's Research Agenda",
|
||||
|
||||
"target": "Thinking Fast and Slow",
|
||||
|
||||
"distance": 3.3333333333333335,
|
||||
|
||||
"reasoning": ""
|
||||
|
||||
},
|
||||
|
||||
{
|
||||
|
||||
"source": "Thinking Fast and Slow",
|
||||
|
||||
"target": "Superintelligence",
|
||||
|
||||
"distance": "200",
|
||||
|
||||
"reasoning": "Yeah yeah I know I'm contradicting myself"
|
||||
|
||||
},
|
||||
|
||||
{
|
||||
|
||||
"source": "The Mathematical Theory of Communication",
|
||||
|
||||
"target": "Superintelligence",
|
||||
|
||||
"distance": "60",
|
||||
|
||||
"reasoning": ""
|
||||
|
||||
},
|
||||
|
||||
{
|
||||
|
||||
"source": "Categorizing Variants of Goodhart's Law",
|
||||
|
||||
"target": "The Vulnerable World Hypothesis",
|
||||
|
||||
"distance": 10,
|
||||
|
||||
"reasoning": ""
|
||||
|
||||
},
|
||||
|
||||
{
|
||||
|
||||
"source": "The motivated reasoning critique of effective altruism",
|
||||
|
||||
"target": "Shallow evaluations of longtermist organizations",
|
||||
|
||||
"distance": "4",
|
||||
|
||||
"reasoning": ""
|
||||
|
||||
},
|
||||
|
||||
{
|
||||
|
||||
"source": "The motivated reasoning critique of effective altruism",
|
||||
|
||||
"target": "Categorizing Variants of Goodhart's Law",
|
||||
|
||||
"distance": 2,
|
||||
|
||||
"reasoning": ""
|
||||
|
||||
},
|
||||
|
||||
{
|
||||
|
||||
"source": "Categorizing Variants of Goodhart's Law",
|
||||
|
||||
"target": "Shallow evaluations of longtermist organizations",
|
||||
|
||||
"distance": "4",
|
||||
|
||||
"reasoning": ""
|
||||
|
||||
},
|
||||
|
||||
{
|
||||
|
||||
"source": "Shallow evaluations of longtermist organizations",
|
||||
|
||||
"target": "The Vulnerable World Hypothesis",
|
||||
|
||||
"distance": 200,
|
||||
|
||||
"reasoning": ""
|
||||
|
||||
},
|
||||
|
||||
{
|
||||
|
||||
"source": "The motivated reasoning critique of effective altruism",
|
||||
|
||||
"target": "The Global Priorities Institute's Research Agenda",
|
||||
|
||||
"distance": 10,
|
||||
|
||||
"reasoning": ""
|
||||
|
||||
},
|
||||
|
||||
{
|
||||
|
||||
"source": "Categorizing Variants of Goodhart's Law",
|
||||
|
||||
"target": "The Global Priorities Institute's Research Agenda",
|
||||
|
||||
"distance": 5,
|
||||
|
||||
"reasoning": ""
|
||||
|
||||
},
|
||||
|
||||
{
|
||||
|
||||
"source": "Shallow evaluations of longtermist organizations",
|
||||
|
||||
"target": "The Global Priorities Institute's Research Agenda",
|
||||
|
||||
"distance": 2.5,
|
||||
|
||||
"reasoning": ""
|
||||
|
||||
},
|
||||
|
||||
{
|
||||
|
||||
"source": "The Global Priorities Institute's Research Agenda",
|
||||
|
||||
"target": "The Vulnerable World Hypothesis",
|
||||
|
||||
"distance": "10",
|
||||
|
||||
"reasoning": ""
|
||||
|
||||
},
|
||||
|
||||
{
|
||||
|
||||
"source": "Thinking Fast and Slow",
|
||||
|
||||
"target": "The Vulnerable World Hypothesis",
|
||||
|
||||
"distance": "2",
|
||||
|
||||
"reasoning": ""
|
||||
|
||||
},
|
||||
|
||||
{
|
||||
|
||||
"source": "The Vulnerable World Hypothesis",
|
||||
|
||||
"target": "The Mathematical Theory of Communication",
|
||||
|
||||
"distance": 5,
|
||||
|
||||
"reasoning": ""
|
||||
|
||||
},
|
||||
|
||||
{
|
||||
|
||||
"source": "Reversals in Psychology",
|
||||
|
||||
"target": "A Model of Patient Spending and Movement Building",
|
||||
|
||||
"distance": 2.5,
|
||||
|
||||
"reasoning": ""
|
||||
|
||||
},
|
||||
|
||||
{
|
||||
|
||||
"source": "What are some low-information priors that you find practically useful for thinking about the world?",
|
||||
|
||||
"target": "Database of orgs relevant to longtermist/x-risk work",
|
||||
|
||||
"distance": 2.5,
|
||||
|
||||
"reasoning": ""
|
||||
|
||||
},
|
||||
|
||||
{
|
||||
|
||||
"source": "What are some low-information priors that you find practically useful for thinking about the world?",
|
||||
|
||||
"target": "Reversals in Psychology",
|
||||
|
||||
"distance": 1.4285714285714286,
|
||||
|
||||
"reasoning": ""
|
||||
|
||||
},
|
||||
|
||||
{
|
||||
|
||||
"source": "Reversals in Psychology",
|
||||
|
||||
"target": "Database of orgs relevant to longtermist/x-risk work",
|
||||
|
||||
"distance": "4",
|
||||
|
||||
"reasoning": ""
|
||||
|
||||
},
|
||||
|
||||
{
|
||||
|
||||
"source": "A Model of Patient Spending and Movement Building",
|
||||
|
||||
"target": "Database of orgs relevant to longtermist/x-risk work",
|
||||
|
||||
"distance": "2",
|
||||
|
||||
"reasoning": ""
|
||||
|
||||
},
|
||||
|
||||
{
|
||||
|
||||
"source": "Center for Election Science EA Wiki stub",
|
||||
|
||||
"target": "Extinguishing or preventing coal seam fires is a potential cause area",
|
||||
|
||||
"distance": 10,
|
||||
|
||||
"reasoning": ""
|
||||
|
||||
},
|
||||
|
||||
{
|
||||
|
||||
"source": "Center for Election Science EA Wiki stub",
|
||||
|
||||
"target": "A comment on setting up a charity",
|
||||
|
||||
"distance": "3",
|
||||
|
||||
"reasoning": ""
|
||||
|
||||
},
|
||||
|
||||
{
|
||||
|
||||
"source": "A comment on setting up a charity",
|
||||
|
||||
"target": "Extinguishing or preventing coal seam fires is a potential cause area",
|
||||
|
||||
"distance": 2,
|
||||
|
||||
"reasoning": ""
|
||||
|
||||
},
|
||||
|
||||
{
|
||||
|
||||
"source": "Center for Election Science EA Wiki stub",
|
||||
|
||||
"target": "What are some low-information priors that you find practically useful for thinking about the world?",
|
||||
|
||||
"distance": 2,
|
||||
|
||||
"reasoning": ""
|
||||
|
||||
},
|
||||
|
||||
{
|
||||
|
||||
"source": "A comment on setting up a charity",
|
||||
|
||||
"target": "What are some low-information priors that you find practically useful for thinking about the world?",
|
||||
|
||||
"distance": 2,
|
||||
|
||||
"reasoning": ""
|
||||
|
||||
},
|
||||
|
||||
{
|
||||
|
||||
"source": "What are some low-information priors that you find practically useful for thinking about the world?",
|
||||
|
||||
"target": "Extinguishing or preventing coal seam fires is a potential cause area",
|
||||
|
||||
"distance": "4",
|
||||
|
||||
"reasoning": ""
|
||||
|
||||
},
|
||||
|
||||
{
|
||||
|
||||
"source": "Reversals in Psychology",
|
||||
|
||||
"target": "Extinguishing or preventing coal seam fires is a potential cause area",
|
||||
|
||||
"distance": "5",
|
||||
|
||||
"reasoning": ""
|
||||
|
||||
},
|
||||
|
||||
{
|
||||
|
||||
"source": "A Model of Patient Spending and Movement Building",
|
||||
|
||||
"target": "Extinguishing or preventing coal seam fires is a potential cause area",
|
||||
|
||||
"distance": "3",
|
||||
|
||||
"reasoning": ""
|
||||
|
||||
},
|
||||
|
||||
{
|
||||
|
||||
"source": "Database of orgs relevant to longtermist/x-risk work",
|
||||
|
||||
"target": "Extinguishing or preventing coal seam fires is a potential cause area",
|
||||
|
||||
"distance": "2",
|
||||
|
||||
"reasoning": ""
|
||||
|
||||
},
|
||||
|
||||
{
|
||||
|
||||
"source": "Center for Election Science EA Wiki stub",
|
||||
|
||||
"target": "The motivated reasoning critique of effective altruism",
|
||||
|
||||
"distance": 5,
|
||||
|
||||
"reasoning": ""
|
||||
|
||||
},
|
||||
|
||||
{
|
||||
|
||||
"source": "A comment on setting up a charity",
|
||||
|
||||
"target": "The motivated reasoning critique of effective altruism",
|
||||
|
||||
"distance": 1.6666666666666667,
|
||||
|
||||
"reasoning": ""
|
||||
|
||||
},
|
||||
|
||||
{
|
||||
|
||||
"source": "The motivated reasoning critique of effective altruism",
|
||||
|
||||
"target": "What are some low-information priors that you find practically useful for thinking about the world?",
|
||||
|
||||
"distance": "5",
|
||||
|
||||
"reasoning": ""
|
||||
|
||||
},
|
||||
|
||||
{
|
||||
|
||||
"source": "What are some low-information priors that you find practically useful for thinking about the world?",
|
||||
|
||||
"target": "Categorizing Variants of Goodhart's Law",
|
||||
|
||||
"distance": 5,
|
||||
|
||||
"reasoning": ""
|
||||
|
||||
},
|
||||
|
||||
{
|
||||
|
||||
"source": "Reversals in Psychology",
|
||||
|
||||
"target": "Categorizing Variants of Goodhart's Law",
|
||||
|
||||
"distance": 3.3333333333333335,
|
||||
|
||||
"reasoning": ""
|
||||
|
||||
},
|
||||
|
||||
{
|
||||
|
||||
"source": "Categorizing Variants of Goodhart's Law",
|
||||
|
||||
"target": "A Model of Patient Spending and Movement Building",
|
||||
|
||||
"distance": "8",
|
||||
|
||||
"reasoning": ""
|
||||
|
||||
},
|
||||
|
||||
{
|
||||
|
||||
"source": "A Model of Patient Spending and Movement Building",
|
||||
|
||||
"target": "Shallow evaluations of longtermist organizations",
|
||||
|
||||
"distance": 5,
|
||||
|
||||
"reasoning": ""
|
||||
|
||||
},
|
||||
|
||||
{
|
||||
|
||||
"source": "Database of orgs relevant to longtermist/x-risk work",
|
||||
|
||||
"target": "Shallow evaluations of longtermist organizations",
|
||||
|
||||
"distance": 2.5,
|
||||
|
||||
"reasoning": ""
|
||||
|
||||
},
|
||||
|
||||
{
|
||||
|
||||
"source": "Shallow evaluations of longtermist organizations",
|
||||
|
||||
"target": "Extinguishing or preventing coal seam fires is a potential cause area",
|
||||
|
||||
"distance": 1,
|
||||
|
||||
"reasoning": ""
|
||||
|
||||
},
|
||||
|
||||
{
|
||||
|
||||
"source": "Extinguishing or preventing coal seam fires is a potential cause area",
|
||||
|
||||
"target": "The Global Priorities Institute's Research Agenda",
|
||||
|
||||
"distance": 2,
|
||||
|
||||
"reasoning": ""
|
||||
|
||||
}
|
||||
|
||||
]
|
|
@ -1,534 +0,0 @@
|
|||
[
|
||||
|
||||
{
|
||||
|
||||
"source": "Thinking Fast and Slow",
|
||||
|
||||
"target": "The Global Priorities Institute's Research Agenda",
|
||||
|
||||
"distance": "100",
|
||||
|
||||
"reasoning": "",
|
||||
|
||||
"squiggleString": "100"
|
||||
|
||||
},
|
||||
|
||||
{
|
||||
|
||||
"source": "The Global Priorities Institute's Research Agenda",
|
||||
|
||||
"target": "The Mathematical Theory of Communication",
|
||||
|
||||
"distance": 1000,
|
||||
|
||||
"reasoning": "",
|
||||
|
||||
"squiggleString": 1000
|
||||
|
||||
},
|
||||
|
||||
{
|
||||
|
||||
"source": "Superintelligence",
|
||||
|
||||
"target": "The Mathematical Theory of Communication",
|
||||
|
||||
"distance": 10,
|
||||
|
||||
"reasoning": "",
|
||||
|
||||
"squiggleString": 10
|
||||
|
||||
},
|
||||
|
||||
{
|
||||
|
||||
"source": "Categorizing Variants of Goodhart's Law",
|
||||
|
||||
"target": "The Vulnerable World Hypothesis",
|
||||
|
||||
"distance": 10,
|
||||
|
||||
"reasoning": "",
|
||||
|
||||
"squiggleString": 10
|
||||
|
||||
},
|
||||
|
||||
{
|
||||
|
||||
"source": "Shallow evaluations of longtermist organizations",
|
||||
|
||||
"target": "The motivated reasoning critique of effective altruism",
|
||||
|
||||
"distance": 10,
|
||||
|
||||
"reasoning": "",
|
||||
|
||||
"squiggleString": 10
|
||||
|
||||
},
|
||||
|
||||
{
|
||||
|
||||
"source": "Shallow evaluations of longtermist organizations",
|
||||
|
||||
"target": "Categorizing Variants of Goodhart's Law",
|
||||
|
||||
"distance": 100,
|
||||
|
||||
"reasoning": "",
|
||||
|
||||
"squiggleString": 100
|
||||
|
||||
},
|
||||
|
||||
{
|
||||
|
||||
"source": "The motivated reasoning critique of effective altruism",
|
||||
|
||||
"target": "Categorizing Variants of Goodhart's Law",
|
||||
|
||||
"distance": 10,
|
||||
|
||||
"reasoning": "",
|
||||
|
||||
"squiggleString": 10
|
||||
|
||||
},
|
||||
|
||||
{
|
||||
|
||||
"source": "Shallow evaluations of longtermist organizations",
|
||||
|
||||
"target": "Thinking Fast and Slow",
|
||||
|
||||
"distance": 10,
|
||||
|
||||
"reasoning": "",
|
||||
|
||||
"squiggleString": 10
|
||||
|
||||
},
|
||||
|
||||
{
|
||||
|
||||
"source": "Thinking Fast and Slow",
|
||||
|
||||
"target": "The motivated reasoning critique of effective altruism",
|
||||
|
||||
"distance": 1,
|
||||
|
||||
"reasoning": "",
|
||||
|
||||
"squiggleString": 1
|
||||
|
||||
},
|
||||
|
||||
{
|
||||
|
||||
"source": "The motivated reasoning critique of effective altruism",
|
||||
|
||||
"target": "The Global Priorities Institute's Research Agenda",
|
||||
|
||||
"distance": 1000,
|
||||
|
||||
"reasoning": "",
|
||||
|
||||
"squiggleString": 1000
|
||||
|
||||
},
|
||||
|
||||
{
|
||||
|
||||
"source": "Categorizing Variants of Goodhart's Law",
|
||||
|
||||
"target": "The Global Priorities Institute's Research Agenda",
|
||||
|
||||
"distance": 100,
|
||||
|
||||
"reasoning": "",
|
||||
|
||||
"squiggleString": 100
|
||||
|
||||
},
|
||||
|
||||
{
|
||||
|
||||
"source": "The Vulnerable World Hypothesis",
|
||||
|
||||
"target": "The Global Priorities Institute's Research Agenda",
|
||||
|
||||
"distance": 10,
|
||||
|
||||
"reasoning": "",
|
||||
|
||||
"squiggleString": 10
|
||||
|
||||
},
|
||||
|
||||
{
|
||||
|
||||
"source": "Reversals in Psychology",
|
||||
|
||||
"target": "A Model of Patient Spending and Movement Building",
|
||||
|
||||
"distance": 10,
|
||||
|
||||
"reasoning": "RiP: Cleaning up 10,000 people's brains a bit.\nMPS: far more important topic",
|
||||
|
||||
"squiggleString": 10
|
||||
|
||||
},
|
||||
|
||||
{
|
||||
|
||||
"source": "Database of orgs relevant to longtermist/x-risk work",
|
||||
|
||||
"target": "What are some low-information priors that you find practically useful for thinking about the world?",
|
||||
|
||||
"distance": "5",
|
||||
|
||||
"reasoning": "\nDatabase just saves a bit of time, maybe 100 counterfactual applications",
|
||||
|
||||
"squiggleString": "5"
|
||||
|
||||
},
|
||||
|
||||
{
|
||||
|
||||
"source": "Reversals in Psychology",
|
||||
|
||||
"target": "Database of orgs relevant to longtermist/x-risk work",
|
||||
|
||||
"distance": 1,
|
||||
|
||||
"reasoning": "",
|
||||
|
||||
"squiggleString": 1
|
||||
|
||||
},
|
||||
|
||||
{
|
||||
|
||||
"source": "Database of orgs relevant to longtermist/x-risk work",
|
||||
|
||||
"target": "A Model of Patient Spending and Movement Building",
|
||||
|
||||
"distance": 10,
|
||||
|
||||
"reasoning": "",
|
||||
|
||||
"squiggleString": 10
|
||||
|
||||
},
|
||||
|
||||
{
|
||||
|
||||
"source": "What are some low-information priors that you find practically useful for thinking about the world?",
|
||||
|
||||
"target": "A Model of Patient Spending and Movement Building",
|
||||
|
||||
"distance": 2,
|
||||
|
||||
"reasoning": "",
|
||||
|
||||
"squiggleString": 2
|
||||
|
||||
},
|
||||
|
||||
{
|
||||
|
||||
"source": "Center for Election Science EA Wiki stub",
|
||||
|
||||
"target": "Extinguishing or preventing coal seam fires is a potential cause area",
|
||||
|
||||
"distance": 1000,
|
||||
|
||||
"reasoning": "",
|
||||
|
||||
"squiggleString": 1000
|
||||
|
||||
},
|
||||
|
||||
{
|
||||
|
||||
"source": "A comment on setting up a charity",
|
||||
|
||||
"target": "Center for Election Science EA Wiki stub",
|
||||
|
||||
"distance": 10,
|
||||
|
||||
"reasoning": "",
|
||||
|
||||
"squiggleString": 10
|
||||
|
||||
},
|
||||
|
||||
{
|
||||
|
||||
"source": "A comment on setting up a charity",
|
||||
|
||||
"target": "Reversals in Psychology",
|
||||
|
||||
"distance": 200,
|
||||
|
||||
"reasoning": "",
|
||||
|
||||
"squiggleString": 200
|
||||
|
||||
},
|
||||
|
||||
{
|
||||
|
||||
"source": "Center for Election Science EA Wiki stub",
|
||||
|
||||
"target": "Reversals in Psychology",
|
||||
|
||||
"distance": 20,
|
||||
|
||||
"reasoning": "",
|
||||
|
||||
"squiggleString": 20
|
||||
|
||||
},
|
||||
|
||||
{
|
||||
|
||||
"source": "Reversals in Psychology",
|
||||
|
||||
"target": "Extinguishing or preventing coal seam fires is a potential cause area",
|
||||
|
||||
"distance": "50",
|
||||
|
||||
"reasoning": "",
|
||||
|
||||
"squiggleString": "50"
|
||||
|
||||
},
|
||||
|
||||
{
|
||||
|
||||
"source": "Database of orgs relevant to longtermist/x-risk work",
|
||||
|
||||
"target": "Extinguishing or preventing coal seam fires is a potential cause area",
|
||||
|
||||
"distance": "50",
|
||||
|
||||
"reasoning": "",
|
||||
|
||||
"squiggleString": "50"
|
||||
|
||||
},
|
||||
|
||||
{
|
||||
|
||||
"source": "What are some low-information priors that you find practically useful for thinking about the world?",
|
||||
|
||||
"target": "Extinguishing or preventing coal seam fires is a potential cause area",
|
||||
|
||||
"distance": "10",
|
||||
|
||||
"reasoning": "",
|
||||
|
||||
"squiggleString": "10"
|
||||
|
||||
},
|
||||
|
||||
{
|
||||
|
||||
"source": "A Model of Patient Spending and Movement Building",
|
||||
|
||||
"target": "Extinguishing or preventing coal seam fires is a potential cause area",
|
||||
|
||||
"distance": 1,
|
||||
|
||||
"reasoning": "",
|
||||
|
||||
"squiggleString": 1
|
||||
|
||||
},
|
||||
|
||||
{
|
||||
|
||||
"source": "A comment on setting up a charity",
|
||||
|
||||
"target": "Shallow evaluations of longtermist organizations",
|
||||
|
||||
"distance": 1000,
|
||||
|
||||
"reasoning": "",
|
||||
|
||||
"squiggleString": 1000
|
||||
|
||||
},
|
||||
|
||||
{
|
||||
|
||||
"source": "Center for Election Science EA Wiki stub",
|
||||
|
||||
"target": "Shallow evaluations of longtermist organizations",
|
||||
|
||||
"distance": 100,
|
||||
|
||||
"reasoning": "",
|
||||
|
||||
"squiggleString": 100
|
||||
|
||||
},
|
||||
|
||||
{
|
||||
|
||||
"source": "Reversals in Psychology",
|
||||
|
||||
"target": "Shallow evaluations of longtermist organizations",
|
||||
|
||||
"distance": 100,
|
||||
|
||||
"reasoning": "",
|
||||
|
||||
"squiggleString": 100
|
||||
|
||||
},
|
||||
|
||||
{
|
||||
|
||||
"source": "Database of orgs relevant to longtermist/x-risk work",
|
||||
|
||||
"target": "Shallow evaluations of longtermist organizations",
|
||||
|
||||
"distance": 100,
|
||||
|
||||
"reasoning": "",
|
||||
|
||||
"squiggleString": 100
|
||||
|
||||
},
|
||||
|
||||
{
|
||||
|
||||
"source": "Thinking Fast and Slow",
|
||||
|
||||
"target": "The Mathematical Theory of Communication",
|
||||
|
||||
"distance": 99999.99999999999,
|
||||
|
||||
"reasoning": "",
|
||||
|
||||
"squiggleString": 99999.99999999999
|
||||
|
||||
},
|
||||
|
||||
{
|
||||
|
||||
"source": "What are some low-information priors that you find practically useful for thinking about the world?",
|
||||
|
||||
"target": "Shallow evaluations of longtermist organizations",
|
||||
|
||||
"distance": 100,
|
||||
|
||||
"reasoning": "",
|
||||
|
||||
"squiggleString": 100
|
||||
|
||||
},
|
||||
|
||||
{
|
||||
|
||||
"source": "Shallow evaluations of longtermist organizations",
|
||||
|
||||
"target": "A Model of Patient Spending and Movement Building",
|
||||
|
||||
"distance": 1,
|
||||
|
||||
"reasoning": "",
|
||||
|
||||
"squiggleString": 1
|
||||
|
||||
},
|
||||
|
||||
{
|
||||
|
||||
"source": "Thinking Fast and Slow",
|
||||
|
||||
"target": "A Model of Patient Spending and Movement Building",
|
||||
|
||||
"distance": "1000",
|
||||
|
||||
"reasoning": "",
|
||||
|
||||
"squiggleString": "1000"
|
||||
|
||||
},
|
||||
|
||||
{
|
||||
|
||||
"source": "The motivated reasoning critique of effective altruism",
|
||||
|
||||
"target": "A Model of Patient Spending and Movement Building",
|
||||
|
||||
"distance": "5",
|
||||
|
||||
"reasoning": "",
|
||||
|
||||
"squiggleString": "5"
|
||||
|
||||
},
|
||||
|
||||
{
|
||||
|
||||
"source": "A Model of Patient Spending and Movement Building",
|
||||
|
||||
"target": "Categorizing Variants of Goodhart's Law",
|
||||
|
||||
"distance": 10,
|
||||
|
||||
"reasoning": "",
|
||||
|
||||
"squiggleString": 10
|
||||
|
||||
},
|
||||
|
||||
{
|
||||
|
||||
"source": "Extinguishing or preventing coal seam fires is a potential cause area",
|
||||
|
||||
"target": "Categorizing Variants of Goodhart's Law",
|
||||
|
||||
"distance": 10000,
|
||||
|
||||
"reasoning": "",
|
||||
|
||||
"squiggleString": 10000
|
||||
|
||||
},
|
||||
|
||||
{
|
||||
|
||||
"source": "Thinking Fast and Slow",
|
||||
|
||||
"target": "The Mathematical Theory of Communication",
|
||||
|
||||
"distance": 99999.99999999999,
|
||||
|
||||
"reasoning": "",
|
||||
|
||||
"squiggleString": 99999.99999999999
|
||||
|
||||
},
|
||||
|
||||
{
|
||||
|
||||
"source": "The Global Priorities Institute's Research Agenda",
|
||||
|
||||
"target": "Superintelligence",
|
||||
|
||||
"distance": 100,
|
||||
|
||||
"reasoning": "",
|
||||
|
||||
"squiggleString": 100
|
||||
|
||||
}
|
||||
]
|
|
@ -1,372 +0,0 @@
|
|||
[
|
||||
{
|
||||
"source": "The Global Priorities Institute's Research Agenda",
|
||||
|
||||
"target": "Superintelligence",
|
||||
|
||||
"distance": 100,
|
||||
|
||||
"reasoning": "GPI: good stuff but v v hard questions read by ~200.\nSuperintelligence: Maybe 50,000 copies? associated interview tour transformed the field."
|
||||
},
|
||||
|
||||
{
|
||||
"source": "Thinking Fast and Slow",
|
||||
|
||||
"target": "The Global Priorities Institute's Research Agenda",
|
||||
|
||||
"distance": "100",
|
||||
|
||||
"reasoning": ""
|
||||
},
|
||||
|
||||
{
|
||||
"source": "The Global Priorities Institute's Research Agenda",
|
||||
|
||||
"target": "The Mathematical Theory of Communication",
|
||||
|
||||
"distance": 1000,
|
||||
|
||||
"reasoning": ""
|
||||
},
|
||||
|
||||
{
|
||||
"source": "Superintelligence",
|
||||
|
||||
"target": "The Mathematical Theory of Communication",
|
||||
|
||||
"distance": 10,
|
||||
|
||||
"reasoning": ""
|
||||
},
|
||||
|
||||
{
|
||||
"source": "Categorizing Variants of Goodhart's Law",
|
||||
|
||||
"target": "The Vulnerable World Hypothesis",
|
||||
|
||||
"distance": 10,
|
||||
|
||||
"reasoning": ""
|
||||
},
|
||||
|
||||
{
|
||||
"source": "Shallow evaluations of longtermist organizations",
|
||||
|
||||
"target": "The motivated reasoning critique of effective altruism",
|
||||
|
||||
"distance": 10,
|
||||
|
||||
"reasoning": ""
|
||||
},
|
||||
|
||||
{
|
||||
"source": "Shallow evaluations of longtermist organizations",
|
||||
|
||||
"target": "Categorizing Variants of Goodhart's Law",
|
||||
|
||||
"distance": 100,
|
||||
|
||||
"reasoning": ""
|
||||
},
|
||||
|
||||
{
|
||||
"source": "The motivated reasoning critique of effective altruism",
|
||||
|
||||
"target": "Categorizing Variants of Goodhart's Law",
|
||||
|
||||
"distance": 10,
|
||||
|
||||
"reasoning": ""
|
||||
},
|
||||
|
||||
{
|
||||
"source": "Shallow evaluations of longtermist organizations",
|
||||
|
||||
"target": "Thinking Fast and Slow",
|
||||
|
||||
"distance": 10,
|
||||
|
||||
"reasoning": ""
|
||||
},
|
||||
|
||||
{
|
||||
"source": "Thinking Fast and Slow",
|
||||
|
||||
"target": "The motivated reasoning critique of effective altruism",
|
||||
|
||||
"distance": 1,
|
||||
|
||||
"reasoning": ""
|
||||
},
|
||||
|
||||
{
|
||||
"source": "The motivated reasoning critique of effective altruism",
|
||||
|
||||
"target": "The Global Priorities Institute's Research Agenda",
|
||||
|
||||
"distance": 1000,
|
||||
|
||||
"reasoning": ""
|
||||
},
|
||||
|
||||
{
|
||||
"source": "Categorizing Variants of Goodhart's Law",
|
||||
|
||||
"target": "The Global Priorities Institute's Research Agenda",
|
||||
|
||||
"distance": 100,
|
||||
|
||||
"reasoning": ""
|
||||
},
|
||||
|
||||
{
|
||||
"source": "The Vulnerable World Hypothesis",
|
||||
|
||||
"target": "The Global Priorities Institute's Research Agenda",
|
||||
|
||||
"distance": 10,
|
||||
|
||||
"reasoning": ""
|
||||
},
|
||||
|
||||
{
|
||||
"source": "Reversals in Psychology",
|
||||
|
||||
"target": "A Model of Patient Spending and Movement Building",
|
||||
|
||||
"distance": 10,
|
||||
|
||||
"reasoning": "RiP: Cleaning up 10,000 people's brains a bit.\nMPS: far more important topic"
|
||||
},
|
||||
|
||||
{
|
||||
"source": "Database of orgs relevant to longtermist/x-risk work",
|
||||
|
||||
"target": "What are some low-information priors that you find practically useful for thinking about the world?",
|
||||
|
||||
"distance": "5",
|
||||
|
||||
"reasoning": "\nDatabase just saves a bit of time, maybe 100 counterfactual applications"
|
||||
},
|
||||
|
||||
{
|
||||
"source": "Reversals in Psychology",
|
||||
|
||||
"target": "Database of orgs relevant to longtermist/x-risk work",
|
||||
|
||||
"distance": 1,
|
||||
|
||||
"reasoning": ""
|
||||
},
|
||||
|
||||
{
|
||||
"source": "Database of orgs relevant to longtermist/x-risk work",
|
||||
|
||||
"target": "A Model of Patient Spending and Movement Building",
|
||||
|
||||
"distance": 10,
|
||||
|
||||
"reasoning": ""
|
||||
},
|
||||
|
||||
{
|
||||
"source": "What are some low-information priors that you find practically useful for thinking about the world?",
|
||||
|
||||
"target": "A Model of Patient Spending and Movement Building",
|
||||
|
||||
"distance": 2,
|
||||
|
||||
"reasoning": ""
|
||||
},
|
||||
|
||||
{
|
||||
"source": "Center for Election Science EA Wiki stub",
|
||||
|
||||
"target": "Extinguishing or preventing coal seam fires is a potential cause area",
|
||||
|
||||
"distance": 1000,
|
||||
|
||||
"reasoning": ""
|
||||
},
|
||||
|
||||
{
|
||||
"source": "A comment on setting up a charity",
|
||||
|
||||
"target": "Center for Election Science EA Wiki stub",
|
||||
|
||||
"distance": 10,
|
||||
|
||||
"reasoning": ""
|
||||
},
|
||||
|
||||
{
|
||||
"source": "A comment on setting up a charity",
|
||||
|
||||
"target": "Reversals in Psychology",
|
||||
|
||||
"distance": 200,
|
||||
|
||||
"reasoning": ""
|
||||
},
|
||||
|
||||
{
|
||||
"source": "Center for Election Science EA Wiki stub",
|
||||
|
||||
"target": "Reversals in Psychology",
|
||||
|
||||
"distance": 20,
|
||||
|
||||
"reasoning": ""
|
||||
},
|
||||
|
||||
{
|
||||
"source": "Reversals in Psychology",
|
||||
|
||||
"target": "Extinguishing or preventing coal seam fires is a potential cause area",
|
||||
|
||||
"distance": "50",
|
||||
|
||||
"reasoning": ""
|
||||
},
|
||||
|
||||
{
|
||||
"source": "Database of orgs relevant to longtermist/x-risk work",
|
||||
|
||||
"target": "Extinguishing or preventing coal seam fires is a potential cause area",
|
||||
|
||||
"distance": "50",
|
||||
|
||||
"reasoning": ""
|
||||
},
|
||||
|
||||
{
|
||||
"source": "What are some low-information priors that you find practically useful for thinking about the world?",
|
||||
|
||||
"target": "Extinguishing or preventing coal seam fires is a potential cause area",
|
||||
|
||||
"distance": "10",
|
||||
|
||||
"reasoning": ""
|
||||
},
|
||||
|
||||
{
|
||||
"source": "A Model of Patient Spending and Movement Building",
|
||||
|
||||
"target": "Extinguishing or preventing coal seam fires is a potential cause area",
|
||||
|
||||
"distance": 1,
|
||||
|
||||
"reasoning": ""
|
||||
},
|
||||
|
||||
{
|
||||
"source": "A comment on setting up a charity",
|
||||
|
||||
"target": "Shallow evaluations of longtermist organizations",
|
||||
|
||||
"distance": 1000,
|
||||
|
||||
"reasoning": ""
|
||||
},
|
||||
|
||||
{
|
||||
"source": "Center for Election Science EA Wiki stub",
|
||||
|
||||
"target": "Shallow evaluations of longtermist organizations",
|
||||
|
||||
"distance": 100,
|
||||
|
||||
"reasoning": ""
|
||||
},
|
||||
|
||||
{
|
||||
"source": "Reversals in Psychology",
|
||||
|
||||
"target": "Shallow evaluations of longtermist organizations",
|
||||
|
||||
"distance": 100,
|
||||
|
||||
"reasoning": ""
|
||||
},
|
||||
|
||||
{
|
||||
"source": "Database of orgs relevant to longtermist/x-risk work",
|
||||
|
||||
"target": "Shallow evaluations of longtermist organizations",
|
||||
|
||||
"distance": 100,
|
||||
|
||||
"reasoning": ""
|
||||
},
|
||||
|
||||
{
|
||||
"source": "Thinking Fast and Slow",
|
||||
|
||||
"target": "The Mathematical Theory of Communication",
|
||||
|
||||
"distance": 99999.99999999999,
|
||||
|
||||
"reasoning": ""
|
||||
},
|
||||
|
||||
{
|
||||
"source": "What are some low-information priors that you find practically useful for thinking about the world?",
|
||||
|
||||
"target": "Shallow evaluations of longtermist organizations",
|
||||
|
||||
"distance": 100,
|
||||
|
||||
"reasoning": ""
|
||||
},
|
||||
|
||||
{
|
||||
"source": "Shallow evaluations of longtermist organizations",
|
||||
|
||||
"target": "A Model of Patient Spending and Movement Building",
|
||||
|
||||
"distance": 1,
|
||||
|
||||
"reasoning": ""
|
||||
},
|
||||
|
||||
{
|
||||
"source": "Thinking Fast and Slow",
|
||||
|
||||
"target": "A Model of Patient Spending and Movement Building",
|
||||
|
||||
"distance": "1000",
|
||||
|
||||
"reasoning": ""
|
||||
},
|
||||
|
||||
{
|
||||
"source": "The motivated reasoning critique of effective altruism",
|
||||
|
||||
"target": "A Model of Patient Spending and Movement Building",
|
||||
|
||||
"distance": "5",
|
||||
|
||||
"reasoning": ""
|
||||
},
|
||||
|
||||
{
|
||||
"source": "A Model of Patient Spending and Movement Building",
|
||||
|
||||
"target": "Categorizing Variants of Goodhart's Law",
|
||||
|
||||
"distance": 10,
|
||||
|
||||
"reasoning": ""
|
||||
},
|
||||
|
||||
{
|
||||
"source": "Extinguishing or preventing coal seam fires is a potential cause area",
|
||||
|
||||
"target": "Categorizing Variants of Goodhart's Law",
|
||||
|
||||
"distance": 10000,
|
||||
|
||||
"reasoning": ""
|
||||
}
|
||||
]
|
||||
|
|
@ -1,224 +0,0 @@
|
|||
[
|
||||
{
|
||||
"source": "Thinking Fast and Slow",
|
||||
"target": "The Mathematical Theory of Communication",
|
||||
"distance": 1000,
|
||||
"reasoning": "Jaime Sevilla\nThinking Fast and Slow is a recounting of the evidence about cogsci at the time, and large parts are already outdated.\nTMToC is an enduring piece of theory that kickstarted a new field "
|
||||
},
|
||||
{
|
||||
"source": "The Global Priorities Institute's Research Agenda",
|
||||
"target": "Superintelligence",
|
||||
"distance": 20,
|
||||
"reasoning": "Jaime Sevilla\nI am unsure about the quality difference, but Superintelligence has had a far wider reach"
|
||||
},
|
||||
{
|
||||
"source": "The Global Priorities Institute's Research Agenda",
|
||||
"target": "Thinking Fast and Slow",
|
||||
"distance": 20,
|
||||
"reasoning": "Thinking Fast and Slow has had wider reach, and is a good synthesis of the field."
|
||||
},
|
||||
{
|
||||
"source": "Thinking Fast and Slow",
|
||||
"target": "Superintelligence",
|
||||
"distance": "1.1",
|
||||
"reasoning": "Jaime Sevilla\nSuperintelligence gave prominence to the AI Safety field, possibly bringing forward research timelines a few years.\nThinking Fast and Slow made CogSci available to many people.\nLarge parts of both books are now outdated"
|
||||
},
|
||||
{
|
||||
"source": "Superintelligence",
|
||||
"target": "The Mathematical Theory of Communication",
|
||||
"distance": 1000,
|
||||
"reasoning": "Jaime Sevilla\nTMToC has stood the test of time"
|
||||
},
|
||||
{
|
||||
"source": "Categorizing Variants of Goodhart's Law",
|
||||
"target": "The Vulnerable World Hypothesis",
|
||||
"distance": 33.333333333333336,
|
||||
"reasoning": "TVWH has had wider reach"
|
||||
},
|
||||
{
|
||||
"source": "The motivated reasoning critique of effective altruism",
|
||||
"target": "Shallow evaluations of longtermist organizations",
|
||||
"distance": "2",
|
||||
"reasoning": "Shallow evaluations contains more object level information"
|
||||
},
|
||||
{
|
||||
"source": "The motivated reasoning critique of effective altruism",
|
||||
"target": "Categorizing Variants of Goodhart's Law",
|
||||
"distance": 100,
|
||||
"reasoning": "Goodhart contains more insight"
|
||||
},
|
||||
{
|
||||
"source": "Shallow evaluations of longtermist organizations",
|
||||
"target": "Categorizing Variants of Goodhart's Law",
|
||||
"distance": 20,
|
||||
"reasoning": "Goodhart contains more insights"
|
||||
},
|
||||
{
|
||||
"source": "The motivated reasoning critique of effective altruism",
|
||||
"target": "The Global Priorities Institute's Research Agenda",
|
||||
"distance": 100,
|
||||
"reasoning": "GPIRA has presumably helped at least GPI set its agenda, and possibly other newcomers to the field.\nThe motivated reasoning critique might have helped some EAs by reiterating a core message"
|
||||
},
|
||||
{
|
||||
"source": "Shallow evaluations of longtermist organizations",
|
||||
"target": "The Global Priorities Institute's Research Agenda",
|
||||
"distance": 12.5,
|
||||
"reasoning": "GPIRA helped GPI set their priorities and decompose the problem, shallow evaluations is an experiment on institution evaluation which might result in more work later (I feel like I am not getting at the true reason for my scoring here)"
|
||||
},
|
||||
{
|
||||
"source": "Categorizing Variants of Goodhart's Law",
|
||||
"target": "The Global Priorities Institute's Research Agenda",
|
||||
"distance": 1.1111111111111112,
|
||||
"reasoning": "Research agendas can mobilize more talent, they can be a multiplier.\nBut Goodhearts law is tangible progress on a problem.\nOverall Im confused"
|
||||
},
|
||||
{
|
||||
"source": "The Global Priorities Institute's Research Agenda",
|
||||
"target": "The Vulnerable World Hypothesis",
|
||||
"distance": "10",
|
||||
"reasoning": "vulnerable world had wider reach, and inspired more people"
|
||||
},
|
||||
{
|
||||
"source": "The Vulnerable World Hypothesis",
|
||||
"target": "Thinking Fast and Slow",
|
||||
"distance": 5,
|
||||
"reasoning": "Thinking fast and slow reached more people"
|
||||
},
|
||||
{
|
||||
"source": "A Model of Patient Spending and Movement Building",
|
||||
"target": "Reversals in Psychology",
|
||||
"distance": "10",
|
||||
"reasoning": "I have heard more discussion of reversals than of AMPSMB"
|
||||
},
|
||||
{
|
||||
"source": "What are some low-information priors that you find practically useful for thinking about the world?",
|
||||
"target": "Database of orgs relevant to longtermist/x-risk work",
|
||||
"distance": 10,
|
||||
"reasoning": "I learned a couple of things in the low-information priors post but I think curating databases is very very helpful"
|
||||
},
|
||||
{
|
||||
"source": "What are some low-information priors that you find practically useful for thinking about the world?",
|
||||
"target": "A Model of Patient Spending and Movement Building",
|
||||
"distance": 1.25,
|
||||
"reasoning": "I personally learned more from low information priors, but I havent engaged with patient spending enough to evaluate its value"
|
||||
},
|
||||
{
|
||||
"source": "Database of orgs relevant to longtermist/x-risk work",
|
||||
"target": "A Model of Patient Spending and Movement Building",
|
||||
"distance": 1.1111111111111112,
|
||||
"reasoning": "I think its slighly more likely I will build on top of the patient spending than on top of the database"
|
||||
},
|
||||
{
|
||||
"source": "Center for Election Science EA Wiki stub",
|
||||
"target": "Extinguishing or preventing coal seam fires is a potential cause area",
|
||||
"distance": 100,
|
||||
"reasoning": "Coal article seems more in-depth reasoning "
|
||||
},
|
||||
{
|
||||
"source": "A comment on setting up a charity",
|
||||
"target": "Center for Election Science EA Wiki stub",
|
||||
"distance": 10,
|
||||
"reasoning": "I imagine the wiki stub will reach more people"
|
||||
},
|
||||
{
|
||||
"source": "A comment on setting up a charity",
|
||||
"target": "What are some low-information priors that you find practically useful for thinking about the world?",
|
||||
"distance": 25,
|
||||
"reasoning": "I learned more from low info priors"
|
||||
},
|
||||
{
|
||||
"source": "Center for Election Science EA Wiki stub",
|
||||
"target": "What are some low-information priors that you find practically useful for thinking about the world?",
|
||||
"distance": 12.5,
|
||||
"reasoning": "Learned more from low info priors"
|
||||
},
|
||||
{
|
||||
"source": "What are some low-information priors that you find practically useful for thinking about the world?",
|
||||
"target": "Extinguishing or preventing coal seam fires is a potential cause area",
|
||||
"distance": "1.5",
|
||||
"reasoning": "I learned more from low info priors but I expect I would learn more if I engaged with coal seam fires"
|
||||
},
|
||||
{
|
||||
"source": "Database of orgs relevant to longtermist/x-risk work",
|
||||
"target": "Extinguishing or preventing coal seam fires is a potential cause area",
|
||||
"distance": "1.5",
|
||||
"reasoning": "Database seems more reemplazable"
|
||||
},
|
||||
{
|
||||
"source": "Extinguishing or preventing coal seam fires is a potential cause area",
|
||||
"target": "A Model of Patient Spending and Movement Building",
|
||||
"distance": 1.1111111111111112,
|
||||
"reasoning": "I have no idea of which one would be more useful to me if I engaged with them\nI guess patient spending is more related to my work"
|
||||
},
|
||||
{
|
||||
"source": "A comment on setting up a charity",
|
||||
"target": "The motivated reasoning critique of effective altruism",
|
||||
"distance": 100,
|
||||
"reasoning": "The motivated reasoning critique is better at setting a good culture"
|
||||
},
|
||||
{
|
||||
"source": "Center for Election Science EA Wiki stub",
|
||||
"target": "The motivated reasoning critique of effective altruism",
|
||||
"distance": 12.5,
|
||||
"reasoning": "The motivated reasoning critique is better at setting a good culture"
|
||||
},
|
||||
{
|
||||
"source": "The motivated reasoning critique of effective altruism",
|
||||
"target": "What are some low-information priors that you find practically useful for thinking about the world?",
|
||||
"distance": "1.1",
|
||||
"reasoning": "I learned more from priors, critique is better at setting a culture"
|
||||
},
|
||||
{
|
||||
"source": "What are some low-information priors that you find practically useful for thinking about the world?",
|
||||
"target": "Shallow evaluations of longtermist organizations",
|
||||
"distance": 10,
|
||||
"reasoning": "Shallow evaluations has more object level content"
|
||||
},
|
||||
{
|
||||
"source": "Database of orgs relevant to longtermist/x-risk work",
|
||||
"target": "Shallow evaluations of longtermist organizations",
|
||||
"distance": 1.1111111111111112,
|
||||
"reasoning": "Shallow evaluations contains more crystallized reasoning"
|
||||
},
|
||||
{
|
||||
"source": "Shallow evaluations of longtermist organizations",
|
||||
"target": "Extinguishing or preventing coal seam fires is a potential cause area",
|
||||
"distance": "1.8",
|
||||
"reasoning": "I expect I would learn more from coal seam if I engaged with it"
|
||||
},
|
||||
{
|
||||
"source": "Extinguishing or preventing coal seam fires is a potential cause area",
|
||||
"target": "Categorizing Variants of Goodhart's Law",
|
||||
"distance": 12.5,
|
||||
"reasoning": "Goodhart is more hard-to-replace progress "
|
||||
},
|
||||
{
|
||||
"source": "A Model of Patient Spending and Movement Building",
|
||||
"target": "Categorizing Variants of Goodhart's Law",
|
||||
"distance": 3.3333333333333335,
|
||||
"reasoning": "Goodheart feels like more hard-to-replace progress"
|
||||
},
|
||||
{
|
||||
"source": "Categorizing Variants of Goodhart's Law",
|
||||
"target": "Reversals in Psychology",
|
||||
"distance": "2",
|
||||
"reasoning": "reversals has had more reach"
|
||||
},
|
||||
{
|
||||
"source": "The Global Priorities Institute's Research Agenda",
|
||||
"target": "Reversals in Psychology",
|
||||
"distance": "3",
|
||||
"reasoning": "reversals has had more reach"
|
||||
},
|
||||
{
|
||||
"source": "The Vulnerable World Hypothesis",
|
||||
"target": "Reversals in Psychology",
|
||||
"distance": "1.5",
|
||||
"reasoning": "Reversals has had more reach"
|
||||
},
|
||||
{
|
||||
"source": "Reversals in Psychology",
|
||||
"target": "Thinking Fast and Slow",
|
||||
"distance": 1.4285714285714286,
|
||||
"reasoning": "Oof Im stumped.\nI think thinking fast and slow is enough of a good crystallization of knowledge I am giving it the nod, even though reversals in psychology might have a better insight compression rate"
|
||||
}
|
||||
]
|
|
@ -1,351 +0,0 @@
|
|||
[
|
||||
{
|
||||
"source": "Thinking Fast and Slow",
|
||||
|
||||
"target": "The Mathematical Theory of Communication",
|
||||
|
||||
"distance": 5,
|
||||
|
||||
"reasoning": "This is by Linch."
|
||||
},
|
||||
|
||||
{
|
||||
"source": "The Global Priorities Institute's Research Agenda",
|
||||
|
||||
"target": "Superintelligence",
|
||||
|
||||
"distance": 100,
|
||||
|
||||
"reasoning": ""
|
||||
},
|
||||
|
||||
{
|
||||
"source": "The Global Priorities Institute's Research Agenda",
|
||||
|
||||
"target": "Thinking Fast and Slow",
|
||||
|
||||
"distance": 10,
|
||||
|
||||
"reasoning": ""
|
||||
},
|
||||
|
||||
{
|
||||
"source": "Thinking Fast and Slow",
|
||||
|
||||
"target": "Superintelligence",
|
||||
|
||||
"distance": "10",
|
||||
|
||||
"reasoning": ""
|
||||
},
|
||||
|
||||
{
|
||||
"source": "The Mathematical Theory of Communication",
|
||||
|
||||
"target": "Superintelligence",
|
||||
|
||||
"distance": "50",
|
||||
|
||||
"reasoning": ""
|
||||
},
|
||||
|
||||
{
|
||||
"source": "Categorizing Variants of Goodhart's Law",
|
||||
|
||||
"target": "The Vulnerable World Hypothesis",
|
||||
|
||||
"distance": 10,
|
||||
|
||||
"reasoning": ""
|
||||
},
|
||||
|
||||
{
|
||||
"source": "The motivated reasoning critique of effective altruism",
|
||||
|
||||
"target": "Shallow evaluations of longtermist organizations",
|
||||
|
||||
"distance": "5",
|
||||
|
||||
"reasoning": ""
|
||||
},
|
||||
|
||||
{
|
||||
"source": "The motivated reasoning critique of effective altruism",
|
||||
|
||||
"target": "Categorizing Variants of Goodhart's Law",
|
||||
|
||||
"distance": 100,
|
||||
|
||||
"reasoning": ""
|
||||
},
|
||||
|
||||
{
|
||||
"source": "Shallow evaluations of longtermist organizations",
|
||||
|
||||
"target": "Categorizing Variants of Goodhart's Law",
|
||||
|
||||
"distance": 20,
|
||||
|
||||
"reasoning": ""
|
||||
},
|
||||
|
||||
{
|
||||
"source": "The motivated reasoning critique of effective altruism",
|
||||
|
||||
"target": "The Global Priorities Institute's Research Agenda",
|
||||
|
||||
"distance": 50,
|
||||
|
||||
"reasoning": ""
|
||||
},
|
||||
|
||||
{
|
||||
"source": "Shallow evaluations of longtermist organizations",
|
||||
|
||||
"target": "The Global Priorities Institute's Research Agenda",
|
||||
|
||||
"distance": 10,
|
||||
|
||||
"reasoning": ""
|
||||
},
|
||||
|
||||
{
|
||||
"source": "Categorizing Variants of Goodhart's Law",
|
||||
|
||||
"target": "The Global Priorities Institute's Research Agenda",
|
||||
|
||||
"distance": 2,
|
||||
|
||||
"reasoning": ""
|
||||
},
|
||||
|
||||
{
|
||||
"source": "The Global Priorities Institute's Research Agenda",
|
||||
|
||||
"target": "The Vulnerable World Hypothesis",
|
||||
|
||||
"distance": "5",
|
||||
|
||||
"reasoning": ""
|
||||
},
|
||||
|
||||
{
|
||||
"source": "Thinking Fast and Slow",
|
||||
|
||||
"target": "The Vulnerable World Hypothesis",
|
||||
|
||||
"distance": "3",
|
||||
|
||||
"reasoning": ""
|
||||
},
|
||||
|
||||
{
|
||||
"source": "The Mathematical Theory of Communication",
|
||||
|
||||
"target": "The Vulnerable World Hypothesis",
|
||||
|
||||
"distance": 1,
|
||||
|
||||
"reasoning": ""
|
||||
},
|
||||
|
||||
{
|
||||
"source": "The Vulnerable World Hypothesis",
|
||||
|
||||
"target": "Superintelligence",
|
||||
|
||||
"distance": 10,
|
||||
|
||||
"reasoning": ""
|
||||
},
|
||||
|
||||
{
|
||||
"source": "A Model of Patient Spending and Movement Building",
|
||||
|
||||
"target": "Reversals in Psychology",
|
||||
|
||||
"distance": 1,
|
||||
|
||||
"reasoning": ""
|
||||
},
|
||||
|
||||
{
|
||||
"source": "Database of orgs relevant to longtermist/x-risk work",
|
||||
|
||||
"target": "What are some low-information priors that you find practically useful for thinking about the world?",
|
||||
|
||||
"distance": "2",
|
||||
|
||||
"reasoning": ""
|
||||
},
|
||||
|
||||
{
|
||||
"source": "Database of orgs relevant to longtermist/x-risk work",
|
||||
|
||||
"target": "A Model of Patient Spending and Movement Building",
|
||||
|
||||
"distance": 1.3333333333333333,
|
||||
|
||||
"reasoning": ""
|
||||
},
|
||||
|
||||
{
|
||||
"source": "A Model of Patient Spending and Movement Building",
|
||||
|
||||
"target": "What are some low-information priors that you find practically useful for thinking about the world?",
|
||||
|
||||
"distance": "1.5",
|
||||
|
||||
"reasoning": ""
|
||||
},
|
||||
|
||||
{
|
||||
"source": "Reversals in Psychology",
|
||||
|
||||
"target": "What are some low-information priors that you find practically useful for thinking about the world?",
|
||||
|
||||
"distance": "1.5",
|
||||
|
||||
"reasoning": ""
|
||||
},
|
||||
|
||||
{
|
||||
"source": "Center for Election Science EA Wiki stub",
|
||||
|
||||
"target": "Extinguishing or preventing coal seam fires is a potential cause area",
|
||||
|
||||
"distance": 5,
|
||||
|
||||
"reasoning": ""
|
||||
},
|
||||
|
||||
{
|
||||
"source": "Center for Election Science EA Wiki stub",
|
||||
|
||||
"target": "A comment on setting up a charity",
|
||||
|
||||
"distance": 1,
|
||||
|
||||
"reasoning": ""
|
||||
},
|
||||
|
||||
{
|
||||
"source": "A comment on setting up a charity",
|
||||
|
||||
"target": "Extinguishing or preventing coal seam fires is a potential cause area",
|
||||
|
||||
"distance": 5,
|
||||
|
||||
"reasoning": ""
|
||||
},
|
||||
|
||||
{
|
||||
"source": "Center for Election Science EA Wiki stub",
|
||||
|
||||
"target": "Database of orgs relevant to longtermist/x-risk work",
|
||||
|
||||
"distance": 100,
|
||||
|
||||
"reasoning": ""
|
||||
},
|
||||
|
||||
{
|
||||
"source": "A comment on setting up a charity",
|
||||
|
||||
"target": "Database of orgs relevant to longtermist/x-risk work",
|
||||
|
||||
"distance": 100,
|
||||
|
||||
"reasoning": ""
|
||||
},
|
||||
|
||||
{
|
||||
"source": "Extinguishing or preventing coal seam fires is a potential cause area",
|
||||
|
||||
"target": "Database of orgs relevant to longtermist/x-risk work",
|
||||
|
||||
"distance": 20,
|
||||
|
||||
"reasoning": ""
|
||||
},
|
||||
|
||||
{
|
||||
"source": "Center for Election Science EA Wiki stub",
|
||||
|
||||
"target": "The motivated reasoning critique of effective altruism",
|
||||
|
||||
"distance": 14.285714285714285,
|
||||
|
||||
"reasoning": ""
|
||||
},
|
||||
|
||||
{
|
||||
"source": "A comment on setting up a charity",
|
||||
|
||||
"target": "The motivated reasoning critique of effective altruism",
|
||||
|
||||
"distance": 16.666666666666668,
|
||||
|
||||
"reasoning": ""
|
||||
},
|
||||
|
||||
{
|
||||
"source": "The motivated reasoning critique of effective altruism",
|
||||
|
||||
"target": "Extinguishing or preventing coal seam fires is a potential cause area",
|
||||
|
||||
"distance": "2",
|
||||
|
||||
"reasoning": ""
|
||||
},
|
||||
|
||||
{
|
||||
"source": "Extinguishing or preventing coal seam fires is a potential cause area",
|
||||
|
||||
"target": "Shallow evaluations of longtermist organizations",
|
||||
|
||||
"distance": 2.5,
|
||||
|
||||
"reasoning": ""
|
||||
},
|
||||
|
||||
{
|
||||
"source": "Database of orgs relevant to longtermist/x-risk work",
|
||||
|
||||
"target": "Shallow evaluations of longtermist organizations",
|
||||
|
||||
"distance": 3.3333333333333335,
|
||||
|
||||
"reasoning": ""
|
||||
},
|
||||
|
||||
{
|
||||
"source": "A Model of Patient Spending and Movement Building",
|
||||
|
||||
"target": "Shallow evaluations of longtermist organizations",
|
||||
|
||||
"distance": 5,
|
||||
|
||||
"reasoning": ""
|
||||
},
|
||||
|
||||
{
|
||||
"source": "Reversals in Psychology",
|
||||
|
||||
"target": "Shallow evaluations of longtermist organizations",
|
||||
|
||||
"distance": 10,
|
||||
|
||||
"reasoning": ""
|
||||
},
|
||||
|
||||
{
|
||||
"source": "What are some low-information priors that you find practically useful for thinking about the world?",
|
||||
|
||||
"target": "Shallow evaluations of longtermist organizations",
|
||||
|
||||
"distance": 5,
|
||||
|
||||
"reasoning": ""
|
||||
}
|
||||
]
|
|
@ -1,399 +0,0 @@
|
|||
[
|
||||
|
||||
{
|
||||
|
||||
"source": "Thinking Fast and Slow",
|
||||
|
||||
"target": "The Mathematical Theory of Communication",
|
||||
|
||||
"distance": 10000,
|
||||
|
||||
"reasoning": "Information theory is fundamental. Thinking Fast and Slow is somewhat wrong and not as important in a grand scheme of things. It offered some meta cognitive skills but... They don't seem that valuable 5+y later."
|
||||
|
||||
},
|
||||
|
||||
{
|
||||
|
||||
"source": "The Global Priorities Institute's Research Agenda",
|
||||
|
||||
"target": "Superintelligence",
|
||||
|
||||
"distance": 20,
|
||||
|
||||
"reasoning": "Misha Yagudin\n\nHard choice. Mostly intuition about how many times AI is more important and relative difference in how foundational it have been.\n\n\n\n"
|
||||
|
||||
},
|
||||
|
||||
{
|
||||
|
||||
"source": "Thinking Fast and Slow",
|
||||
|
||||
"target": "The Global Priorities Institute's Research Agenda",
|
||||
|
||||
"distance": "100",
|
||||
|
||||
"reasoning": ""
|
||||
|
||||
},
|
||||
|
||||
{
|
||||
|
||||
"source": "The Global Priorities Institute's Research Agenda",
|
||||
|
||||
"target": "The Mathematical Theory of Communication",
|
||||
|
||||
"distance": 10,
|
||||
|
||||
"reasoning": "Or something like that. "
|
||||
|
||||
},
|
||||
|
||||
{
|
||||
|
||||
"source": "Superintelligence",
|
||||
|
||||
"target": "The Mathematical Theory of Communication",
|
||||
|
||||
"distance": 2,
|
||||
|
||||
"reasoning": "Misha\n\nI know I am incoherent...\n\nBut SI is less fundamental but still important"
|
||||
|
||||
},
|
||||
|
||||
{
|
||||
|
||||
"source": "Categorizing Variants of Goodhart's Law",
|
||||
|
||||
"target": "The Vulnerable World Hypothesis",
|
||||
|
||||
"distance": 33.333333333333336,
|
||||
|
||||
"reasoning": "VWH is the best argument against liberty. GL is good paper but clearly less important. "
|
||||
|
||||
},
|
||||
|
||||
{
|
||||
|
||||
"source": "Shallow evaluations of longtermist organizations",
|
||||
|
||||
"target": "The motivated reasoning critique of effective altruism",
|
||||
|
||||
"distance": 10,
|
||||
|
||||
"reasoning": "Misha \n\nI think the later might be more influential via CEA community health team. But low chances.\n\nAs a research direction the first is more important. But it feels inconsequential."
|
||||
|
||||
},
|
||||
|
||||
{
|
||||
|
||||
"source": "Shallow evaluations of longtermist organizations",
|
||||
|
||||
"target": "Categorizing Variants of Goodhart's Law",
|
||||
|
||||
"distance": 10,
|
||||
|
||||
"reasoning": "AI stuff is more important; AI stuff gives more general mental models"
|
||||
|
||||
},
|
||||
|
||||
{
|
||||
|
||||
"source": "The motivated reasoning critique of effective altruism",
|
||||
|
||||
"target": "Categorizing Variants of Goodhart's Law",
|
||||
|
||||
"distance": 5,
|
||||
|
||||
"reasoning": "Or something. AI is more important and more generalizable but community meta is still fairly important. \n\nI think meta will target worse thinkers on average hence difference."
|
||||
|
||||
},
|
||||
|
||||
{
|
||||
|
||||
"source": "Shallow evaluations of longtermist organizations",
|
||||
|
||||
"target": "Thinking Fast and Slow",
|
||||
|
||||
"distance": 66.66666666666667,
|
||||
|
||||
"reasoning": "It's a bit hard. I am fairly dismissive of TFaS but it's a book and some ideas are good."
|
||||
|
||||
},
|
||||
|
||||
{
|
||||
|
||||
"source": "The motivated reasoning critique of effective altruism",
|
||||
|
||||
"target": "Thinking Fast and Slow",
|
||||
|
||||
"distance": 25,
|
||||
|
||||
"reasoning": ""
|
||||
|
||||
},
|
||||
|
||||
{
|
||||
|
||||
"source": "Categorizing Variants of Goodhart's Law",
|
||||
|
||||
"target": "Thinking Fast and Slow",
|
||||
|
||||
"distance": 2,
|
||||
|
||||
"reasoning": ""
|
||||
|
||||
},
|
||||
|
||||
{
|
||||
|
||||
"source": "Thinking Fast and Slow",
|
||||
|
||||
"target": "The Vulnerable World Hypothesis",
|
||||
|
||||
"distance": "15",
|
||||
|
||||
"reasoning": "Clearly more important for the world saving."
|
||||
|
||||
},
|
||||
|
||||
{
|
||||
|
||||
"source": "The Global Priorities Institute's Research Agenda",
|
||||
|
||||
"target": "The Vulnerable World Hypothesis",
|
||||
|
||||
"distance": "2",
|
||||
|
||||
"reasoning": "Hard call. VWH feels more urgent than GPI RA. But I tried to disentangle agenda as a piece from its role as a necessary tool for field building. I sorta think that VWH agenda would have been x10+ more valuable per its more immediate focus and applicability to policy."
|
||||
|
||||
},
|
||||
|
||||
{
|
||||
|
||||
"source": "The Vulnerable World Hypothesis",
|
||||
|
||||
"target": "Superintelligence",
|
||||
|
||||
"distance": 10,
|
||||
|
||||
"reasoning": "SI is field building, deeper and about AI."
|
||||
|
||||
},
|
||||
|
||||
{
|
||||
|
||||
"source": "A Model of Patient Spending and Movement Building",
|
||||
|
||||
"target": "Reversals in Psychology",
|
||||
|
||||
"distance": "3",
|
||||
|
||||
"reasoning": "I sorta think that knowing that some psychology is totally fabricated &c is useful for not relying on it in your reasoning about the world and some of these were fairly fundamental. Also another update about quality of social sciences.\n\nI think some updates are clearly x10+ more important but value of categorising them is not as much.\n\nI am not sure how valuable are econ models, tbh."
|
||||
|
||||
},
|
||||
|
||||
{
|
||||
|
||||
"source": "What are some low-information priors that you find practically useful for thinking about the world?",
|
||||
|
||||
"target": "Database of orgs relevant to longtermist/x-risk work",
|
||||
|
||||
"distance": 100,
|
||||
|
||||
"reasoning": "Dunno nothing new to me in the priors question but Pablo's comment which is fairly trivial and I haven't used/thought about it since.\n"
|
||||
|
||||
},
|
||||
|
||||
{
|
||||
|
||||
"source": "What are some low-information priors that you find practically useful for thinking about the world?",
|
||||
|
||||
"target": "A Model of Patient Spending and Movement Building",
|
||||
|
||||
"distance": 500,
|
||||
|
||||
"reasoning": "Sorta even worse"
|
||||
|
||||
},
|
||||
|
||||
{
|
||||
|
||||
"source": "Database of orgs relevant to longtermist/x-risk work",
|
||||
|
||||
"target": "A Model of Patient Spending and Movement Building",
|
||||
|
||||
"distance": 3.3333333333333335,
|
||||
|
||||
"reasoning": "not sure; the later seems more consequential in the future"
|
||||
|
||||
},
|
||||
|
||||
{
|
||||
|
||||
"source": "Center for Election Science EA Wiki stub",
|
||||
|
||||
"target": "Extinguishing or preventing coal seam fires is a potential cause area",
|
||||
|
||||
"distance": 10,
|
||||
|
||||
"reasoning": "No idea how good the later is but Wiki is not particularly insightful. I think think tags for orgs are obv less useful than tags for cause areas. "
|
||||
|
||||
},
|
||||
|
||||
{
|
||||
|
||||
"source": "A comment on setting up a charity",
|
||||
|
||||
"target": "Center for Election Science EA Wiki stub",
|
||||
|
||||
"distance": 100,
|
||||
|
||||
"reasoning": "idk man seems like a random comment might be consequential but let's not count it as research"
|
||||
|
||||
},
|
||||
|
||||
{
|
||||
|
||||
"source": "A comment on setting up a charity",
|
||||
|
||||
"target": "What are some low-information priors that you find practically useful for thinking about the world?",
|
||||
|
||||
"distance": 100,
|
||||
|
||||
"reasoning": ""
|
||||
|
||||
},
|
||||
|
||||
{
|
||||
|
||||
"source": "What are some low-information priors that you find practically useful for thinking about the world?",
|
||||
|
||||
"target": "Center for Election Science EA Wiki stub",
|
||||
|
||||
"distance": 1,
|
||||
|
||||
"reasoning": "I like the later more but both are just lists which turned out not to be of much use to me. I think others will enjoy priors more."
|
||||
|
||||
},
|
||||
|
||||
{
|
||||
|
||||
"source": "Center for Election Science EA Wiki stub",
|
||||
|
||||
"target": "Database of orgs relevant to longtermist/x-risk work",
|
||||
|
||||
"distance": 10,
|
||||
|
||||
"reasoning": ""
|
||||
|
||||
},
|
||||
|
||||
{
|
||||
|
||||
"source": "Extinguishing or preventing coal seam fires is a potential cause area",
|
||||
|
||||
"target": "Database of orgs relevant to longtermist/x-risk work",
|
||||
|
||||
"distance": 2.5,
|
||||
|
||||
"reasoning": "I think lists are cool. But maybe we would have it anyway via tags and maybe fires are actually good.\n\n"
|
||||
|
||||
},
|
||||
|
||||
{
|
||||
|
||||
"source": "A comment on setting up a charity",
|
||||
|
||||
"target": "Shallow evaluations of longtermist organizations",
|
||||
|
||||
"distance": 10000,
|
||||
|
||||
"reasoning": "idk"
|
||||
|
||||
},
|
||||
|
||||
{
|
||||
|
||||
"source": "What are some low-information priors that you find practically useful for thinking about the world?",
|
||||
|
||||
"target": "Shallow evaluations of longtermist organizations",
|
||||
|
||||
"distance": 100,
|
||||
|
||||
"reasoning": ""
|
||||
|
||||
},
|
||||
|
||||
{
|
||||
|
||||
"source": "Center for Election Science EA Wiki stub",
|
||||
|
||||
"target": "Shallow evaluations of longtermist organizations",
|
||||
|
||||
"distance": 200,
|
||||
|
||||
"reasoning": ""
|
||||
|
||||
},
|
||||
|
||||
{
|
||||
|
||||
"source": "Extinguishing or preventing coal seam fires is a potential cause area",
|
||||
|
||||
"target": "Shallow evaluations of longtermist organizations",
|
||||
|
||||
"distance": 10,
|
||||
|
||||
"reasoning": ""
|
||||
|
||||
},
|
||||
|
||||
{
|
||||
|
||||
"source": "Database of orgs relevant to longtermist/x-risk work",
|
||||
|
||||
"target": "Shallow evaluations of longtermist organizations",
|
||||
|
||||
"distance": 10,
|
||||
|
||||
"reasoning": ""
|
||||
|
||||
},
|
||||
|
||||
{
|
||||
|
||||
"source": "Shallow evaluations of longtermist organizations",
|
||||
|
||||
"target": "A Model of Patient Spending and Movement Building",
|
||||
|
||||
"distance": "2",
|
||||
|
||||
"reasoning": "hard call"
|
||||
|
||||
},
|
||||
|
||||
{
|
||||
|
||||
"source": "A Model of Patient Spending and Movement Building",
|
||||
|
||||
"target": "The motivated reasoning critique of effective altruism",
|
||||
|
||||
"distance": 3.3333333333333335,
|
||||
|
||||
"reasoning": ""
|
||||
|
||||
},
|
||||
|
||||
{
|
||||
|
||||
"source": "Reversals in Psychology",
|
||||
|
||||
"target": "The motivated reasoning critique of effective altruism",
|
||||
|
||||
"distance": 1.4285714285714286,
|
||||
|
||||
"reasoning": ""
|
||||
|
||||
}
|
||||
|
||||
]
|
|
@ -1,351 +0,0 @@
|
|||
[
|
||||
{
|
||||
"source": "Thinking Fast and Slow",
|
||||
|
||||
"target": "The Mathematical Theory of Communication",
|
||||
|
||||
"distance": 5,
|
||||
|
||||
"reasoning": ""
|
||||
},
|
||||
|
||||
{
|
||||
"source": "The Global Priorities Institute's Research Agenda",
|
||||
|
||||
"target": "Superintelligence",
|
||||
|
||||
"distance": 3.3333333333333335,
|
||||
|
||||
"reasoning": ""
|
||||
},
|
||||
|
||||
{
|
||||
"source": "The Global Priorities Institute's Research Agenda",
|
||||
|
||||
"target": "Thinking Fast and Slow",
|
||||
|
||||
"distance": 100,
|
||||
|
||||
"reasoning": ""
|
||||
},
|
||||
|
||||
{
|
||||
"source": "Superintelligence",
|
||||
|
||||
"target": "Thinking Fast and Slow",
|
||||
|
||||
"distance": 2.5,
|
||||
|
||||
"reasoning": ""
|
||||
},
|
||||
|
||||
{
|
||||
"source": "Categorizing Variants of Goodhart's Law",
|
||||
|
||||
"target": "The Vulnerable World Hypothesis",
|
||||
|
||||
"distance": 33.333333333333336,
|
||||
|
||||
"reasoning": ""
|
||||
},
|
||||
|
||||
{
|
||||
"source": "The motivated reasoning critique of effective altruism",
|
||||
|
||||
"target": "Shallow evaluations of longtermist organizations",
|
||||
|
||||
"distance": "3",
|
||||
|
||||
"reasoning": ""
|
||||
},
|
||||
|
||||
{
|
||||
"source": "Categorizing Variants of Goodhart's Law",
|
||||
|
||||
"target": "The motivated reasoning critique of effective altruism",
|
||||
|
||||
"distance": 1,
|
||||
|
||||
"reasoning": ""
|
||||
},
|
||||
|
||||
{
|
||||
"source": "The motivated reasoning critique of effective altruism",
|
||||
|
||||
"target": "The Vulnerable World Hypothesis",
|
||||
|
||||
"distance": 100,
|
||||
|
||||
"reasoning": ""
|
||||
},
|
||||
|
||||
{
|
||||
"source": "Shallow evaluations of longtermist organizations",
|
||||
|
||||
"target": "The Vulnerable World Hypothesis",
|
||||
|
||||
"distance": 16.666666666666668,
|
||||
|
||||
"reasoning": ""
|
||||
},
|
||||
|
||||
{
|
||||
"source": "Categorizing Variants of Goodhart's Law",
|
||||
|
||||
"target": "The Global Priorities Institute's Research Agenda",
|
||||
|
||||
"distance": 20,
|
||||
|
||||
"reasoning": ""
|
||||
},
|
||||
|
||||
{
|
||||
"source": "The motivated reasoning critique of effective altruism",
|
||||
|
||||
"target": "The Global Priorities Institute's Research Agenda",
|
||||
|
||||
"distance": 20,
|
||||
|
||||
"reasoning": ""
|
||||
},
|
||||
|
||||
{
|
||||
"source": "Shallow evaluations of longtermist organizations",
|
||||
|
||||
"target": "The Global Priorities Institute's Research Agenda",
|
||||
|
||||
"distance": 20,
|
||||
|
||||
"reasoning": ""
|
||||
},
|
||||
|
||||
{
|
||||
"source": "The Global Priorities Institute's Research Agenda",
|
||||
|
||||
"target": "The Vulnerable World Hypothesis",
|
||||
|
||||
"distance": "5",
|
||||
|
||||
"reasoning": ""
|
||||
},
|
||||
|
||||
{
|
||||
"source": "The Vulnerable World Hypothesis",
|
||||
|
||||
"target": "Superintelligence",
|
||||
|
||||
"distance": 16.666666666666668,
|
||||
|
||||
"reasoning": ""
|
||||
},
|
||||
|
||||
{
|
||||
"source": "A Model of Patient Spending and Movement Building",
|
||||
|
||||
"target": "Reversals in Psychology",
|
||||
|
||||
"distance": "10",
|
||||
|
||||
"reasoning": ""
|
||||
},
|
||||
|
||||
{
|
||||
"source": "Database of orgs relevant to longtermist/x-risk work",
|
||||
|
||||
"target": "What are some low-information priors that you find practically useful for thinking about the world?",
|
||||
|
||||
"distance": "1",
|
||||
|
||||
"reasoning": ""
|
||||
},
|
||||
|
||||
{
|
||||
"source": "Database of orgs relevant to longtermist/x-risk work",
|
||||
|
||||
"target": "A Model of Patient Spending and Movement Building",
|
||||
|
||||
"distance": 20,
|
||||
|
||||
"reasoning": ""
|
||||
},
|
||||
|
||||
{
|
||||
"source": "What are some low-information priors that you find practically useful for thinking about the world?",
|
||||
|
||||
"target": "A Model of Patient Spending and Movement Building",
|
||||
|
||||
"distance": 20,
|
||||
|
||||
"reasoning": ""
|
||||
},
|
||||
|
||||
{
|
||||
"source": "Center for Election Science EA Wiki stub",
|
||||
|
||||
"target": "Extinguishing or preventing coal seam fires is a potential cause area",
|
||||
|
||||
"distance": 2,
|
||||
|
||||
"reasoning": ""
|
||||
},
|
||||
|
||||
{
|
||||
"source": "A comment on setting up a charity",
|
||||
|
||||
"target": "Center for Election Science EA Wiki stub",
|
||||
|
||||
"distance": 5,
|
||||
|
||||
"reasoning": ""
|
||||
},
|
||||
|
||||
{
|
||||
"source": "A comment on setting up a charity",
|
||||
|
||||
"target": "Database of orgs relevant to longtermist/x-risk work",
|
||||
|
||||
"distance": 25,
|
||||
|
||||
"reasoning": ""
|
||||
},
|
||||
|
||||
{
|
||||
"source": "Center for Election Science EA Wiki stub",
|
||||
|
||||
"target": "Database of orgs relevant to longtermist/x-risk work",
|
||||
|
||||
"distance": 3.3333333333333335,
|
||||
|
||||
"reasoning": ""
|
||||
},
|
||||
|
||||
{
|
||||
"source": "Extinguishing or preventing coal seam fires is a potential cause area",
|
||||
|
||||
"target": "Database of orgs relevant to longtermist/x-risk work",
|
||||
|
||||
"distance": 2,
|
||||
|
||||
"reasoning": ""
|
||||
},
|
||||
|
||||
{
|
||||
"source": "A comment on setting up a charity",
|
||||
|
||||
"target": "Categorizing Variants of Goodhart's Law",
|
||||
|
||||
"distance": 500,
|
||||
|
||||
"reasoning": ""
|
||||
},
|
||||
|
||||
{
|
||||
"source": "Center for Election Science EA Wiki stub",
|
||||
|
||||
"target": "Categorizing Variants of Goodhart's Law",
|
||||
|
||||
"distance": 142.85714285714286,
|
||||
|
||||
"reasoning": ""
|
||||
},
|
||||
|
||||
{
|
||||
"source": "Extinguishing or preventing coal seam fires is a potential cause area",
|
||||
|
||||
"target": "Categorizing Variants of Goodhart's Law",
|
||||
|
||||
"distance": 166.66666666666666,
|
||||
|
||||
"reasoning": ""
|
||||
},
|
||||
|
||||
{
|
||||
"source": "Database of orgs relevant to longtermist/x-risk work",
|
||||
|
||||
"target": "Categorizing Variants of Goodhart's Law",
|
||||
|
||||
"distance": 16.666666666666668,
|
||||
|
||||
"reasoning": ""
|
||||
},
|
||||
|
||||
{
|
||||
"source": "What are some low-information priors that you find practically useful for thinking about the world?",
|
||||
|
||||
"target": "Categorizing Variants of Goodhart's Law",
|
||||
|
||||
"distance": 14.285714285714285,
|
||||
|
||||
"reasoning": ""
|
||||
},
|
||||
|
||||
{
|
||||
"source": "A Model of Patient Spending and Movement Building",
|
||||
|
||||
"target": "Categorizing Variants of Goodhart's Law",
|
||||
|
||||
"distance": 2.5,
|
||||
|
||||
"reasoning": ""
|
||||
},
|
||||
|
||||
{
|
||||
"source": "Categorizing Variants of Goodhart's Law",
|
||||
|
||||
"target": "Reversals in Psychology",
|
||||
|
||||
"distance": "10",
|
||||
|
||||
"reasoning": ""
|
||||
},
|
||||
|
||||
{
|
||||
"source": "The motivated reasoning critique of effective altruism",
|
||||
|
||||
"target": "Reversals in Psychology",
|
||||
|
||||
"distance": "20",
|
||||
|
||||
"reasoning": ""
|
||||
},
|
||||
|
||||
{
|
||||
"source": "Shallow evaluations of longtermist organizations",
|
||||
|
||||
"target": "Reversals in Psychology",
|
||||
|
||||
"distance": "70",
|
||||
|
||||
"reasoning": ""
|
||||
},
|
||||
|
||||
{
|
||||
"source": "The Global Priorities Institute's Research Agenda",
|
||||
|
||||
"target": "Reversals in Psychology",
|
||||
|
||||
"distance": "30",
|
||||
|
||||
"reasoning": ""
|
||||
},
|
||||
|
||||
{
|
||||
"source": "The Vulnerable World Hypothesis",
|
||||
|
||||
"target": "Reversals in Psychology",
|
||||
|
||||
"distance": "1",
|
||||
|
||||
"reasoning": ""
|
||||
},
|
||||
|
||||
{
|
||||
"source": "Reversals in Psychology",
|
||||
|
||||
"target": "Superintelligence",
|
||||
|
||||
"distance": 3.3333333333333335,
|
||||
|
||||
"reasoning": ""
|
||||
}
|
||||
]
|
Before Width: | Height: | Size: 289 KiB |
Before Width: | Height: | Size: 294 KiB |
Before Width: | Height: | Size: 336 KiB |
Before Width: | Height: | Size: 282 KiB |
Before Width: | Height: | Size: 266 KiB |
Before Width: | Height: | Size: 294 KiB |
|
@ -1,33 +0,0 @@
|
|||
const sum = (arr) => arr.reduce((a, b) => a + b, 0);
|
||||
|
||||
function getStdev(arr) {
|
||||
if (Array.isArray(arr) && arr.length > 0) {
|
||||
const n = arr.length;
|
||||
const mean = arr.reduce((a, b) => a + b) / n;
|
||||
return Math.sqrt(
|
||||
arr.map((x) => Math.pow(x - mean, 2)).reduce((a, b) => a + b) / n
|
||||
);
|
||||
} else {
|
||||
return 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, numerically
|
||||
let result = Math.exp(logavg / n);
|
||||
return result;
|
||||
};
|
||||
|
||||
export const getCoefficientOfVariation = (arr) => {
|
||||
let nonPositiveNumbers = arr.filter((x) => x <= 0);
|
||||
if (nonPositiveNumbers.length == 0) {
|
||||
let gm = geomMean(arr);
|
||||
let stdev = getStdev(arr);
|
||||
return stdev / gm;
|
||||
} else {
|
||||
return getStdev(arr) / avg(arr);
|
||||
}
|
||||
};
|
|
@ -1,5 +0,0 @@
|
|||
[[plugins]]
|
||||
package = "@netlify/plugin-nextjs"
|
||||
|
||||
[build]
|
||||
publish = ".next"
|
|
@ -1,6 +0,0 @@
|
|||
module.exports = {
|
||||
plugins: {
|
||||
tailwindcss: {},
|
||||
autoprefixer: {},
|
||||
},
|
||||
}
|
Before Width: | Height: | Size: 15 KiB |