Commit 8c3391c9 authored by Vlastislav Dohnal's avatar Vlastislav Dohnal
Browse files

Initial commit from SVN on Andromeda

parents
Loading
Loading
Loading
Loading

.gitignore

0 → 100644
+1 −0
Original line number Diff line number Diff line
/target/

pom.xml

0 → 100644
+21 −0
Original line number Diff line number Diff line
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>mtree</groupId>
    <artifactId>M-tree-optim</artifactId>
    <version>1.0-SNAPSHOT</version>
    <dependencies>
        <dependency>
            <groupId>messif</groupId>
            <artifactId>messif</artifactId>
            <version>2.3.9-DEVEL</version>
        </dependency>
    </dependencies>
    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <maven.compiler.source>14</maven.compiler.source>
        <maven.compiler.target>14</maven.compiler.target>
        <exec.mainClass>mtree.MTreeOptim</exec.mainClass>
    </properties>
</project>
 No newline at end of file
+75 −0
Original line number Diff line number Diff line

import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */

/**
 *
 * @author xdohnal
 */
public class StatsToDB {
    public static void main(String... args) throws FileNotFoundException, IOException {
        String treeFile = "mtree-top9000-leaf100.txt";
        String logFile = "mtree-top9000-leaf100-knn30-all.txt";
        String db = "";
        
        // Structure log...
        try (BufferedReader log = new BufferedReader(new FileReader(treeFile))) {
            String line;
            while ( (line = log.readLine()) != null ) {
                if (line.startsWith("  Leaves:")) {
                    
                    continue;
                }
                if (line.startsWith("Unsorted leaf-node occupations:")) {
                    continue;
                }
            }
        }
         
        // Query log...
        Pattern pOper = Pattern.compile("^.*\\(([^\\)]*)\\).*returned ([0-9]*) objects.*$");
        Pattern pStat = Pattern.compile("^([^:]+): ((?:[0-9.]+)|{(?:[^}]*)})$");
        
        try (BufferedReader log = new BufferedReader(new FileReader(logFile))) {
            String line;
            String qId = null;
            int qAns = 0;
            Map<String,String> stats = new HashMap<>();
            while ((line = log.readLine()) != null) {
                // New query
                if (line.startsWith("KNNQueryOperation ")) {
                    // Process prev query
                    if (qId != null) {
                        
                        stats.clear();
                    }
                    // Read new query
                    Matcher m = pOper.matcher(line);
                    if (m.matches()) {
                        qId = m.group(1);
                        qAns = Integer.valueOf(m.group(2));
                    }
                    continue;
                }
                // Read stats...
                Matcher mStat = pStat.matcher(line);
                if (mStat.matches()) {
                    stats.put(mStat.group(1), mStat.group(2));      // Int stat / Hash stat
                    continue;
                }
            }
        }
    }
}
+72 −0
Original line number Diff line number Diff line
/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package mtree;

import messif.objects.LocalAbstractObject;
import messif.operations.Approximate;

/**
 *
 * @author xdohnal
 */
public class ApproxState {
    protected int limit;
    protected float radiusGuaranteed;
    
    protected int objectsChecked;
    protected int bucketsVisited;
    
    public static ApproxState create(Approximate limits, MTree tree) {
        switch (limits.getLocalSearchType()) {
            case ABS_OBJ_COUNT:
                return new ApproxStateObjects(limits.getLocalSearchParam(), limits.getRadiusGuaranteed());
            case PERCENTAGE:
                return new ApproxStateObjects(Math.round((float)tree.getObjectCount() * (float)limits.getLocalSearchParam() / 100f), limits.getRadiusGuaranteed());
            case DATA_PARTITIONS:
                return new ApproxStateBuckets(limits.getLocalSearchParam(), limits.getRadiusGuaranteed());
            default:
                throw new IllegalArgumentException("Unsupported approximation type: " + limits.getLocalSearchType());
        }
    }

    protected ApproxState(int limit, float radiusGuaranteed) {
        this.limit = limit;
        this.radiusGuaranteed = radiusGuaranteed;
    }
    
    public void update(LeafNode n) {
        objectsChecked += n.getObjectCount();
        bucketsVisited++;
    }
    
    public boolean stop(float headLowerBound) {
        throw new IllegalStateException("ApproxState.stop must be implemented and must not be called!");
    }
    
    private static class ApproxStateBuckets extends ApproxState {
        protected ApproxStateBuckets(int limit, float radiusGuaranteed) {
            super(limit, radiusGuaranteed);
        }
        
        @Override
        public boolean stop(float headLowerBound) {
            return (bucketsVisited >= limit 
                    && (radiusGuaranteed == LocalAbstractObject.UNKNOWN_DISTANCE || headLowerBound > radiusGuaranteed));
        }
    }
    
    private static class ApproxStateObjects extends ApproxState {
        protected ApproxStateObjects(int limit, float radiusGuaranteed) {
            super(limit, radiusGuaranteed);
        }

        @Override
        public boolean stop(float headLowerBound) {
            return (objectsChecked >= limit 
                    && (radiusGuaranteed == LocalAbstractObject.UNKNOWN_DISTANCE || headLowerBound > radiusGuaranteed));
        }
    }
}
+254 −0
Original line number Diff line number Diff line
package mtree;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
import messif.objects.LocalAbstractObject;
import messif.objects.util.AbstractObjectIterator;
import messif.objects.util.AbstractObjectList;

/**
 * M-tree's fork
 * Changes:
 *    = node capacity is in number of objects now!!!
 *
 * @author Jan Sedmidubsky, xsedmid@fi.muni.cz, FI MU Brno, Czech Republic
 */
public class InternalNode extends Node implements Serializable {
    private static final long serialVersionUID = 2L;
    
    /** soft capacity of this node, this capacity can be exceeded (in objects) */
    private long softCapacity;
    
//    /** current occupation of this node in objects */
//    private long occupation = 0l;
    
    /** list of all internal node entries */
    private List<NodeEntry> entryList = new ArrayList<NodeEntry>();
    
    
    
    /****************** Constructors ******************/
    
    public InternalNode(int level, NodeEntry parentNodeEntry, long softCapacity) {
        super(level, parentNodeEntry);
        this.softCapacity = softCapacity;
    }
    
    
    /****************** Methods ******************/
    
    /**
     *  Returns <tt>false</tt> if the capacity of this node after inserting
     *  object o will be exceeded.
     *
     *  @return <tt>false</tt> if the capacity of this node after inserting
     *  object o will be exceeded
     */
    public boolean isFreeCapacity(LocalAbstractObject o) {
        //return occupation + 1 <= softCapacity;
        return entryList.size() < softCapacity;
    }
    
    /**
     *  Creates a new node entry in this node.
     *
     *  @param nhr length of HR array
     *  @return a new node entry
     */
    public NodeEntry createNodeEntry(LocalAbstractObject p, Node subtree, int nhr) {
        
        // Creation of array HR of new object o.
        NodeEntry.HREntry[] hr = new NodeEntry.HREntry[nhr];
        for (int i = 0; i < nhr; i++)
            hr[i] = new NodeEntry.HREntry();
        
        NodeEntry ne = new NodeEntry(this, p, subtree, hr);
        return this.createNodeEntry(ne);
    }
    
    /**
     *  Adds the specified node entry into this node.
     *
     *  @return added node entry
     */
    public NodeEntry createNodeEntry(NodeEntry ne) {
        
        ne.setNode(this);
        entryList.add(ne);
        //occupation++;
        
        return ne;
    }
    
    /**
     *  Returns the node entry at specified position.
     *
     *  @return the node entry at specified position
     */
    public NodeEntry getNodeEntry(int pos) {
	return entryList.get(pos);
    }
    
    /**
     *  Returns the node entry selected by an object stored in it.
     *
     *  @return the node entry selected by an object stored in it
     */
    public NodeEntry getNodeEntry(LocalAbstractObject o) {
        for (NodeEntry ne: entryList) {
            if (ne.getObject().equals(o))
                return ne;
        }
        return null;
    }
    
    /**
     *  Returns a list of stored node entries of this node.
     *
     *  @return a list of stored node entries of this node
     */
    public List<NodeEntry> getNodeEntryList() {
        return entryList;
    }
    
    /**
     *  Removes the specified node entry from this node.
     *
     *  @return <tt>true</tt> if the specified node entry has been removed
     */
    public boolean removeNodeEntry(NodeEntry ne) {
        if (entryList.remove(ne)) {
            return true;
        }
        return false;
    }
    
    /**
     *  Removes the specified node entry from this node.
     *
     *  @return <tt>true</tt> if the specified node entry has been removed
     */
    public boolean removeNodeEntry(NodeEntry ne, Iterator<NodeEntry> nodeEntryIterator) {
        nodeEntryIterator.remove();
        return true;
    }
    
    
    /****************** Implemented class Node ******************/
    
    /**
     *  Returns <tt>false</tt> if the capacity of this node is not exceeded.
     *
     *  @return <tt>false</tt> if the capacity of this node is not exceeded
     */
    public boolean isCapacityExceeded() {
        return entryList.size() > softCapacity;
    }
    
    /**
     *  Returns the number of stored objects in this node.
     *
     *  @return the number of stored objects in this node
     */
    public int getObjectCount() {
        return entryList.size();
    }

    @Override
    public int getNodeCount() {
        int cnt = 1;
        for (NodeEntry ne : entryList)
            cnt += ne.getSubtree().getNodeCount();
        return cnt;
    }
    
    /**
     *	Returns an iterator of all objects stored in this node.
     *
     *  @return an iterator of all objects stored in this node
     */
    public AbstractObjectIterator<LocalAbstractObject> getObjects() {
        AbstractObjectList<LocalAbstractObject> objects = new AbstractObjectList<LocalAbstractObject>();
        for (NodeEntry ne: entryList)
            objects.add(ne.getObject());
        return objects.iterator();
    }
    
    /**
     *  Adjusts the radius of the parent node.
     *
     *  @return <tt>false</tt> if the radius of the parent node hasn't needed
     *  to be adjusted
     */
    protected boolean adjustParentRadius() {
        NodeEntry pne = getParentNodeEntry();
        if (pne == null)
            return false;
        
        // Computation of the radius.
        float r = 0f;
        for (NodeEntry ne: getNodeEntryList()) {
            float d = ne.getParentDist() + ne.getRadius();
            if (r < d)
                r = d;
        }
        
        // Adjustment of the radius.
        if (r != pne.getRadius())
            pne.setRadius(r);
        pne.getNode().adjustParentRadius();
        return true;
    }
    
    /**
     *  Adjusts the distances of HR array of the parent node.
     *
     *  @return <tt>false</tt> if the distances of the parent node haven't
     *  needed to be adjusted
     */
    protected boolean adjustParentHR() {
        NodeEntry pne = getParentNodeEntry();
        if (pne == null)
            return false;
        
        // Computation of the parent HR array.
        NodeEntry.HREntry[] hr = pne.getHR();
        int nhr = hr.length;
        float[] min = new float[nhr];
        float[] max = new float[nhr];
        Arrays.fill(min, Float.MAX_VALUE);
        Arrays.fill(max, 0f);
        
        for (NodeEntry ne: this.getNodeEntryList()) {
            NodeEntry.HREntry[] nehr = ne.getHR();
            for (int l = 0; l < nhr; l++) {
                float minDist = nehr[l].getMin();
                float maxDist = nehr[l].getMax();
                if (minDist < min[l]) min[l] = minDist;
                if (maxDist > max[l]) max[l] = maxDist;
            }
        }
        
        // Adjustment of the parent HR array.
        for (int l = 0; l < nhr; l++) {
            if (hr[l].getMin() != min[l])
                hr[l].setMin(min[l]);
            if (hr[l].getMax() != max[l])
                hr[l].setMax(max[l]);
        }
        pne.getNode().adjustParentHR();
        return true;
    }
    
    
    /****************** Overrided class Object ******************/
    
    @Override
    public String toString() {
        return "Internal node (" + entryList.size() + ")";
    }
    
}