kieker.analysis.generic.clustering.mtree.nodes.AbstractNode Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of kieker Show documentation
Show all versions of kieker Show documentation
Kieker: Application Performance Monitoring and Dynamic Software Analysis
The newest version!
/***************************************************************************
* Copyright 2022 Kieker Project (http://kieker-monitoring.net)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
***************************************************************************/
package kieker.analysis.generic.clustering.mtree.nodes;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import kieker.analysis.exception.InternalErrorException;
import kieker.analysis.generic.clustering.mtree.DistanceFunctionFactory;
import kieker.analysis.generic.clustering.mtree.IDistanceFunction;
import kieker.analysis.generic.clustering.mtree.ILeafness;
import kieker.analysis.generic.clustering.mtree.IRootness;
import kieker.analysis.generic.clustering.mtree.ISplitFunction.SplitResult;
import kieker.analysis.generic.clustering.mtree.MTree;
import kieker.analysis.generic.clustering.mtree.utils.Pair;
/**
* @param
* data element type
*
* @author Eduardo R. D'Avila
*
* @since 2.0.0
*/
public abstract class AbstractNode extends IndexItem {
protected IRootness rootness;
protected ILeafness leafness;
private final Map> children = new HashMap<>();
private final MTree mtree;
protected AbstractNode(final MTree mtree, final T data) {
super(data);
this.mtree = mtree;
}
public Map> getChildren() {
return this.children;
}
public final void addData(final T data, final double distance) throws InternalErrorException {
this.doAddData(data, distance);
}
@Override
public int check() {
super.check();
this.checkMinCapacity();
this.checkMaxCapacity();
int childHeight = -1;
for (final Map.Entry> e : this.children.entrySet()) {
final T data = e.getKey();
final IndexItem child = e.getValue();
assert child.getData().equals(data);
this.checkChildClass(child);
this.checkChildMetrics(child);
final int height = child.check();
if (childHeight < 0) {
childHeight = height;
} else {
assert childHeight == height;
}
}
return childHeight + 1;
}
protected void doAddData(final T data, final double distance) throws InternalErrorException {
this.leafness.doAddData(data, distance);
}
protected boolean doRemoveData(final T data, final double distance) throws InternalErrorException {
return this.leafness.doRemoveData(data, distance);
}
public final boolean isMaxCapacityExceeded() throws InternalErrorException {
return (this.children.size() > this.mtree.getMaxNodeCapacity());
}
public final Pair> splitNodes() throws InternalErrorException {
final IDistanceFunction super T> cachedDistanceFunction = DistanceFunctionFactory.cached(this.mtree.getDistanceFunction());
final SplitResult splitResult = this.mtree.getSplitFunction().process(this.children.keySet(), cachedDistanceFunction);
final AbstractNode newNode0 = this.createNewNode(splitResult, cachedDistanceFunction, 0);
final AbstractNode newNode1 = this.createNewNode(splitResult, cachedDistanceFunction, 1);
assert this.children.isEmpty();
return new Pair<>(newNode0, newNode1);
}
private AbstractNode createNewNode(final SplitResult splitResult, final IDistanceFunction super T> distanceFunction, final int resultIndex)
throws InternalErrorException {
final T promotedData = splitResult.getPromoted().get(resultIndex);
final Set partition = splitResult.getPartitions().get(resultIndex);
final AbstractNode newNode = this.newSplitNodeReplacement(promotedData);
for (final T data : partition) {
final IndexItem child = this.children.get(data);
this.children.remove(data);
final double distance = distanceFunction.calculate(promotedData, data);
newNode.addChild(child, distance);
}
return newNode;
}
protected AbstractNode newSplitNodeReplacement(final T data) {
return this.leafness.newSplitNodeReplacement(data);
}
public void addChild(final IndexItem child, final double distance) throws InternalErrorException {
this.leafness.addChild(child, distance);
}
public boolean removeData(final T data, final double distance)
throws InternalErrorException {
return this.doRemoveData(data, distance);
}
public boolean isNodeUnderCapacity() throws InternalErrorException {
return this.children.size() < this.getMinCapacity();
}
protected int getMinCapacity() throws InternalErrorException {
return this.rootness.getMinCapacity();
}
public void updateMetrics(final IndexItem child, final double distance) {
child.setDistanceToParent(distance);
this.updateRadius(child);
}
public void updateRadius(final IndexItem child) {
this.radius = Math.max(this.radius, child.getDistanceToParent() + child.getRadius());
}
public void checkMinCapacity() {
this.rootness.checkMinCapacity();
}
private void checkMaxCapacity() {
assert this.children.size() <= this.mtree.getMaxNodeCapacity();
}
private void checkChildClass(final IndexItem child) {
this.leafness.checkChildClass(child);
}
private void checkChildMetrics(final IndexItem child) {
final double dist = this.mtree.getDistanceFunction().calculate(child.getData(), this.getData());
assert child.getDistanceToParent() == dist;
final double sum = child.getDistanceToParent() + child.getRadius();
assert sum <= this.radius;
}
@Override
protected void checkDistanceToParent() {
this.rootness.checkDistanceToParent();
}
public MTree getMTree() {
return this.mtree;
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy