mirror of
https://github.com/hsokolowski/iTree.git
synced 2026-06-11 14:24:17 -04:00
Folding and expanding leaves
This commit is contained in:
@@ -55,7 +55,7 @@ function buildDecisionTreeC45(
|
||||
quality: _quality,
|
||||
matchedCount: _positiveCounter,
|
||||
notMatchedCount: _negativeCounter,
|
||||
trainingSet2: trainingSet.map(x => x[categoryAttr]),
|
||||
trainingSet2: trainingSet,
|
||||
};
|
||||
}
|
||||
//console.log(categoryAttr);
|
||||
@@ -81,7 +81,7 @@ function buildDecisionTreeC45(
|
||||
quality: _quality,
|
||||
matchedCount: _positiveCounter,
|
||||
notMatchedCount: _negativeCounter,
|
||||
trainingSet2: trainingSet.map(x => x[categoryAttr]),
|
||||
trainingSet2: trainingSet,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -260,7 +260,7 @@ function buildDecisionTreeC45(
|
||||
quality: _quality,
|
||||
matchedCount: _positiveCounter,
|
||||
notMatchedCount: _negativeCounter,
|
||||
trainingSet2: trainingSet.map(x => x[categoryAttr]),
|
||||
trainingSet2: trainingSet,
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -55,7 +55,7 @@ function buildDecisionTreeTSP(
|
||||
quality: _quality,
|
||||
matchedCount: _positiveCounter,
|
||||
notMatchedCount: _negativeCounter,
|
||||
trainingSet2: trainingSet.map(x => x[categoryAttr]),
|
||||
trainingSet2: trainingSet,
|
||||
};
|
||||
}
|
||||
var attributes = builder.allAttributes.filter(function (el) {
|
||||
@@ -219,7 +219,7 @@ function buildDecisionTreeTSP(
|
||||
quality: _quality,
|
||||
matchedCount: _positiveCounter,
|
||||
notMatchedCount: _negativeCounter,
|
||||
trainingSet2: trainingSet.map(x => x[categoryAttr]),
|
||||
trainingSet2: trainingSet,
|
||||
};
|
||||
}
|
||||
// sprawdzic
|
||||
@@ -244,7 +244,7 @@ function buildDecisionTreeTSP(
|
||||
quality: _quality,
|
||||
matchedCount: _positiveCounter,
|
||||
notMatchedCount: _negativeCounter,
|
||||
trainingSet2: trainingSet.map(x => x[categoryAttr]),
|
||||
trainingSet2: trainingSet,
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
* @param {boolean} isChanged
|
||||
*/
|
||||
//TSP-weight
|
||||
export function buildDecisionTreeTSPW(
|
||||
function buildDecisionTreeTSPW(
|
||||
_builder,
|
||||
isChanged = false,
|
||||
changedAttribute1 = null,
|
||||
@@ -52,7 +52,7 @@ export function buildDecisionTreeTSPW(
|
||||
quality: _quality,
|
||||
matchedCount: _positiveCounter,
|
||||
notMatchedCount: _negativeCounter,
|
||||
trainingSet2: trainingSet.map(x => x[categoryAttr]),
|
||||
trainingSet2: trainingSet,
|
||||
};
|
||||
}
|
||||
var attributes = builder.allAttributes.filter(function (el) {
|
||||
@@ -217,7 +217,7 @@ export function buildDecisionTreeTSPW(
|
||||
quality: _quality,
|
||||
matchedCount: _positiveCounter,
|
||||
notMatchedCount: _negativeCounter,
|
||||
trainingSet2: trainingSet.map(x => x[categoryAttr]),
|
||||
trainingSet2: trainingSet,
|
||||
};
|
||||
}
|
||||
// sprawdzic
|
||||
@@ -242,7 +242,7 @@ export function buildDecisionTreeTSPW(
|
||||
quality: _quality,
|
||||
matchedCount: _positiveCounter,
|
||||
notMatchedCount: _negativeCounter,
|
||||
trainingSet2: trainingSet.map(x => x[categoryAttr]),
|
||||
trainingSet2: trainingSet,
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -11,11 +11,12 @@ import {
|
||||
ModalOverlay,
|
||||
useDisclosure,
|
||||
} from '@chakra-ui/react';
|
||||
import { CloseIcon } from '@chakra-ui/icons';
|
||||
import React, { useState } from 'react';
|
||||
import Configurator from './Configurator';
|
||||
import ModalPopup from './ModalPopup';
|
||||
|
||||
function Joint({ children, attr2, predicateName, pivot, match, notMatch, onChange, nodeSet }) {
|
||||
function Joint({ children, attr2, predicateName, pivot, weight, requestFoldToLeaf, onChange, nodeSet }) {
|
||||
const { isOpen, onOpen, onClose } = useDisclosure();
|
||||
const [size, setSize] = useState('lg');
|
||||
|
||||
@@ -26,6 +27,9 @@ function Joint({ children, attr2, predicateName, pivot, match, notMatch, onChang
|
||||
const buildNewNode = () => {
|
||||
onChange();
|
||||
};
|
||||
|
||||
const foldToLeaf = () => requestFoldToLeaf();
|
||||
|
||||
return (
|
||||
<Box>
|
||||
<Badge
|
||||
@@ -35,9 +39,13 @@ function Joint({ children, attr2, predicateName, pivot, match, notMatch, onChang
|
||||
colorScheme="teal"
|
||||
onClick={handleOpenModalClick}
|
||||
className={'badge'}
|
||||
marginRight={3}
|
||||
>
|
||||
{attr2} <b>{predicateName}</b> {pivot}
|
||||
{attr2} <b>{predicateName}</b> {weight} {pivot}
|
||||
</Badge>
|
||||
<Button size="xs" rightIcon={<CloseIcon />} onClick={foldToLeaf}>
|
||||
Fold
|
||||
</Button>
|
||||
<ModalPopup
|
||||
isOpen={isOpen}
|
||||
nodeSet={nodeSet}
|
||||
@@ -47,6 +55,7 @@ function Joint({ children, attr2, predicateName, pivot, match, notMatch, onChang
|
||||
onChange={onChange}
|
||||
onClose={onClose}
|
||||
onOpen={onOpen}
|
||||
weight={weight}
|
||||
/>
|
||||
{/* <Modal onClose={onClose} size={size} isOpen={isOpen}>
|
||||
<ModalOverlay />
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
import { Box } from '@chakra-ui/react';
|
||||
import { Box, Button, Menu, MenuButton, MenuItem, MenuList } from '@chakra-ui/react';
|
||||
import React from 'react';
|
||||
import { ChevronDownIcon, DownloadIcon } from '@chakra-ui/icons';
|
||||
|
||||
function Leaf({ category, matchedCount, notMatchedCount, quality }) {
|
||||
function Leaf({ category, matchedCount, notMatchedCount, quality, requestLeafUnfold }) {
|
||||
return (
|
||||
<Box
|
||||
d="flex"
|
||||
@@ -36,6 +37,16 @@ function Leaf({ category, matchedCount, notMatchedCount, quality }) {
|
||||
<Box mt="1" ml="2" fontWeight="semibold" as="h4" lineHeight="tight" isTruncated>
|
||||
{quality}%
|
||||
</Box>
|
||||
<Menu closeOnSelect closeOnBlur>
|
||||
<MenuButton fontSize="sm" w={20} h={6} as={Button} rightIcon={<ChevronDownIcon />}>
|
||||
Unfold
|
||||
</MenuButton>
|
||||
<MenuList>
|
||||
<MenuItem onClick={() => requestLeafUnfold('c45')}>C 4.5</MenuItem>
|
||||
<MenuItem onClick={() => requestLeafUnfold('tsp')}>TSP</MenuItem>
|
||||
<MenuItem onClick={() => requestLeafUnfold('tspw')}>TSP Weight</MenuItem>
|
||||
</MenuList>
|
||||
</Menu>
|
||||
</Box>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -11,7 +11,7 @@ import {
|
||||
} from '@chakra-ui/react';
|
||||
import Configurator from './Configurator';
|
||||
|
||||
function ModalPopup({ attr2, predicateName, pivot, isOpen, nodeSet, onOpen, onChange, onClose }) {
|
||||
function ModalPopup({ attr2, predicateName, pivot, weight, isOpen, nodeSet, onOpen, onChange, onClose }) {
|
||||
const handleOnChange = value => {
|
||||
onClose();
|
||||
onChange(value);
|
||||
@@ -32,7 +32,7 @@ function ModalPopup({ attr2, predicateName, pivot, isOpen, nodeSet, onOpen, onCh
|
||||
{x.attr1001} {x[attr2]}-{x[pivot]} {x[attr2] < x[pivot] ? 'Match' : 'NotMatch'}
|
||||
</div>
|
||||
))} */}
|
||||
<Configurator onChange={handleOnChange} attribute={attr2} pivot={pivot} />
|
||||
<Configurator onChange={handleOnChange} attribute={attr2} pivot={pivot} weight={weight} />
|
||||
</ModalBody>
|
||||
<ModalFooter>
|
||||
<Button onClick={onClose}>Close</Button>
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { Spinner } from '@chakra-ui/react';
|
||||
import React, { useEffect, useMemo, useState } from 'react';
|
||||
import { useBuilderConfigContext } from '../../contexts/BuilderConfigContext';
|
||||
import { executeAlgorithm } from '../../utils/algorithm-executor';
|
||||
import { executeAlgorithm, mostFrequentValue } from '../../utils/algorithm-executor';
|
||||
//import { addNode } from "./utils";
|
||||
|
||||
import Joint from './Joint';
|
||||
@@ -25,9 +25,13 @@ const Node = props => {
|
||||
predicateName,
|
||||
pivot,
|
||||
nodeSet,
|
||||
weight,
|
||||
} = node;
|
||||
|
||||
const onNodeClicked = e => {
|
||||
if (!e.target.classList.contains('node')) {
|
||||
return;
|
||||
}
|
||||
//console.log(e);
|
||||
e.stopPropagation();
|
||||
console.log('Node clicked', node);
|
||||
@@ -85,6 +89,29 @@ const Node = props => {
|
||||
props.requestChildChange(targetNode);
|
||||
};
|
||||
|
||||
const foldJointToLeaf = () => {
|
||||
const foldResult = mostFrequentValue(nodeSet, builderConfig.categoryAttr);
|
||||
setNode(foldResult);
|
||||
props.requestChildChange(foldResult);
|
||||
};
|
||||
|
||||
const unfoldLeaf = algorithm => {
|
||||
setLoading(true);
|
||||
executeAlgorithm({
|
||||
...builderConfig,
|
||||
trainingSet: node.trainingSet2,
|
||||
algorithm,
|
||||
})
|
||||
.then(value => {
|
||||
setNode(value);
|
||||
props.requestChildChange(value);
|
||||
})
|
||||
.catch(e => console.error(e))
|
||||
.finally(() => {
|
||||
setLoading(false);
|
||||
});
|
||||
};
|
||||
|
||||
if (loading) {
|
||||
return <Spinner size="xl" />;
|
||||
}
|
||||
@@ -97,6 +124,7 @@ const Node = props => {
|
||||
matchedCount={matchedCount}
|
||||
notMatchedCount={notMatchedCount}
|
||||
quality={quality}
|
||||
requestLeafUnfold={unfoldLeaf}
|
||||
/>
|
||||
) : (
|
||||
<Joint
|
||||
@@ -106,7 +134,9 @@ const Node = props => {
|
||||
match={match}
|
||||
notMatch={notMatch}
|
||||
onChange={onChange}
|
||||
requestFoldToLeaf={foldJointToLeaf}
|
||||
nodeSet={nodeSet}
|
||||
weight={weight}
|
||||
>
|
||||
<Node node={match} onChange={onChange} requestChildChange={requestChildChangeIfMatchIs(true)} />
|
||||
<Node node={notMatch} onChange={onChange} requestChildChange={requestChildChangeIfMatchIs(false)} />
|
||||
|
||||
@@ -17,3 +17,47 @@ export function executeAlgorithm(options, changeOptions = {}) {
|
||||
worker.postMessage({ _builder: { ...options }, ...changeOptions });
|
||||
});
|
||||
}
|
||||
|
||||
function countUniqueValues(items, attr) {
|
||||
var counter = {};
|
||||
|
||||
// detecting different values of attribute
|
||||
for (var i = items.length - 1; i >= 0; i--) {
|
||||
// items[i][attr] - value of attribute
|
||||
counter[items[i][attr]] = 0;
|
||||
}
|
||||
|
||||
// counting number of occurrences of each of values
|
||||
// of attribute
|
||||
for (var j = items.length - 1; j >= 0; j--) {
|
||||
counter[items[j][attr]] += 1;
|
||||
}
|
||||
|
||||
return counter;
|
||||
}
|
||||
|
||||
export function mostFrequentValue(items, attr) {
|
||||
const counter = countUniqueValues(items, attr);
|
||||
|
||||
var mostFrequentCount = 0;
|
||||
var mostFrequentValue;
|
||||
|
||||
for (var value in counter) {
|
||||
if (counter[value] > mostFrequentCount) {
|
||||
mostFrequentCount = counter[value];
|
||||
mostFrequentValue = value;
|
||||
}
|
||||
}
|
||||
|
||||
const _positiveCounter = items.filter(element => element[attr] === mostFrequentValue).length;
|
||||
const _negativeCounter = items.length - _positiveCounter;
|
||||
const _quality = 100 * (_positiveCounter / items.length);
|
||||
|
||||
return {
|
||||
category: mostFrequentValue,
|
||||
quality: _quality.toFixed(2),
|
||||
matchedCount: _positiveCounter,
|
||||
notMatchedCount: _negativeCounter,
|
||||
trainingSet2: items,
|
||||
};
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user