diff --git a/public/algorithms/c45-tree.js b/public/algorithms/c45-tree.js
index b06ad35..25aef5f 100644
--- a/public/algorithms/c45-tree.js
+++ b/public/algorithms/c45-tree.js
@@ -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,
};
}
diff --git a/public/algorithms/tsp-tree.js b/public/algorithms/tsp-tree.js
index b047393..6e1bb08 100644
--- a/public/algorithms/tsp-tree.js
+++ b/public/algorithms/tsp-tree.js
@@ -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,
};
}
diff --git a/public/algorithms/tsp-weight-tree.js b/public/algorithms/tsp-weight-tree.js
index 728052c..8d49e22 100644
--- a/public/algorithms/tsp-weight-tree.js
+++ b/public/algorithms/tsp-weight-tree.js
@@ -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,
};
}
diff --git a/src/components/Node/Joint.jsx b/src/components/Node/Joint.jsx
index 4961af2..16da378 100644
--- a/src/components/Node/Joint.jsx
+++ b/src/components/Node/Joint.jsx
@@ -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 (
- {attr2} {predicateName} {pivot}
+ {attr2} {predicateName} {weight} {pivot}
+ } onClick={foldToLeaf}>
+ Fold
+
{/*
diff --git a/src/components/Node/Leaf.jsx b/src/components/Node/Leaf.jsx
index d077d87..5616849 100644
--- a/src/components/Node/Leaf.jsx
+++ b/src/components/Node/Leaf.jsx
@@ -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 (
{quality}%
+
);
}
diff --git a/src/components/Node/ModalPopup.jsx b/src/components/Node/ModalPopup.jsx
index 9ebf914..0aa8888 100644
--- a/src/components/Node/ModalPopup.jsx
+++ b/src/components/Node/ModalPopup.jsx
@@ -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'}
))} */}
-
+
diff --git a/src/components/Node/index.jsx b/src/components/Node/index.jsx
index 22346ff..e4113ef 100644
--- a/src/components/Node/index.jsx
+++ b/src/components/Node/index.jsx
@@ -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 ;
}
@@ -97,6 +124,7 @@ const Node = props => {
matchedCount={matchedCount}
notMatchedCount={notMatchedCount}
quality={quality}
+ requestLeafUnfold={unfoldLeaf}
/>
) : (
{
match={match}
notMatch={notMatch}
onChange={onChange}
+ requestFoldToLeaf={foldJointToLeaf}
nodeSet={nodeSet}
+ weight={weight}
>
diff --git a/src/utils/algorithm-executor.js b/src/utils/algorithm-executor.js
index 332e0d1..0babc53 100644
--- a/src/utils/algorithm-executor.js
+++ b/src/utils/algorithm-executor.js
@@ -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,
+ };
+}