Commit d8773a47 authored by Vlastislav Dohnal's avatar Vlastislav Dohnal
Browse files

Marker of metric properties backported from MESSIF v3.

ObjectFloatVectorCosine is not a metric!!! Markers applied.
New metric variants of Cosine distance added - ...EuclideanCosine and ...Angular
parent 53e20ffb
Loading
Loading
Loading
Loading
+13 −0
Original line number Diff line number Diff line
/*
 * Click nbfs://nbhost/SystemFileSystem/Templates/Licenses/license-default.txt to change this license
 * Click nbfs://nbhost/SystemFileSystem/Templates/Classes/Class.java to edit this template
 */
package messif.distance;

/**
 * This is a marking interface (no methods) saying that a distance fulfills all metric postulates.
 * @author David Novak, Masaryk University, Brno, Czech Republic, david.novak@fi.muni.cz
 */
public interface Metric extends Reflexive, Symmetric, Triangle {
    
}
+14 −0
Original line number Diff line number Diff line
/*
 * Click nbfs://nbhost/SystemFileSystem/Templates/Licenses/license-default.txt to change this license
 * Click nbfs://nbhost/SystemFileSystem/Templates/Classes/Class.java to edit this template
 */
package messif.distance;

/**
 * This is a marking interface (no methods) saying that a distance fulfills the reflexivity condition.
 * @author David Novak, Masaryk University, Brno, Czech Republic, david.novak@fi.muni.cz
 */
public interface Reflexive {
    
}
+14 −0
Original line number Diff line number Diff line
/*
 * Click nbfs://nbhost/SystemFileSystem/Templates/Licenses/license-default.txt to change this license
 * Click nbfs://nbhost/SystemFileSystem/Templates/Classes/Class.java to edit this template
 */
package messif.distance;

/**
 * This is a marking interface (no methods) saying that a distance fulfills the symmetry.
 * @author David Novak, Masaryk University, Brno, Czech Republic, david.novak@fi.muni.cz
 */
public interface Symmetric {
    
}
+13 −0
Original line number Diff line number Diff line
/*
 * Click nbfs://nbhost/SystemFileSystem/Templates/Licenses/license-default.txt to change this license
 * Click nbfs://nbhost/SystemFileSystem/Templates/Classes/Class.java to edit this template
 */
package messif.distance;

/**
 * This is a marking interface (no methods) saying that a distance fulfills the triangle inequality.
 * @author David Novak, Masaryk University, Brno, Czech Republic, david.novak@fi.muni.cz
 */
public interface Triangle {
    
}
+103 −0
Original line number Diff line number Diff line
/*
 * Click nbfs://nbhost/SystemFileSystem/Templates/Licenses/license-default.txt to change this license
 * Click nbfs://nbhost/SystemFileSystem/Templates/Classes/Class.java to edit this template
 */
package messif.objects.impl;

import java.io.BufferedReader;
import java.io.EOFException;
import java.io.IOException;
import messif.distance.Metric;
import messif.objects.LocalAbstractObject;
import messif.objects.nio.BinaryInput;
import messif.objects.nio.BinarySerializator;

/**
 * Implementation of the {@link ObjectFloatVector} with a Angular <b>metric</b> distance.
 *
 * @author Vlastislav Dohnal, Masaryk University, Brno, Czech Republic, dohnal@fi.muni.cz
 */
public class ObjectFloatVectorAngular extends ObjectFloatVector implements Metric {

    // class id for serialization
    private static final long serialVersionUID = 1L;

    //****************** Constructors ******************//
    /**
     * Creates a new instance of {@link ObjectFloatVectorAngular}.
     *
     * @param data the data content of the new object
     */
    public ObjectFloatVectorAngular(float[] data) {
        super(data);
    }

    /**
     * Creates a new instance of {@link ObjectFloatVectorAngular} with randomly
     * generated content data. Content will be generated using normal
     * distribution of random numbers from interval [min;max).
     *
     * @param dimension number of dimensions to generate
     * @param min lower bound of the random generated values (inclusive)
     * @param max upper bound of the random generated values (exclusive)
     */
    public ObjectFloatVectorAngular(int dimension, float min, float max) {
        super(dimension, min, max);
    }

    /**
     * Creates a new instance of {@link ObjectFloatVectorAngular} from text
     * stream.
     *
     * @param stream the stream from which to read lines of text
     * @throws EOFException if the end-of-file of the given stream is reached
     * @throws IOException if there was an I/O error during reading from the
     * stream
     * @throws NumberFormatException if a line read from the stream does not
     * consist of comma-separated or space-separated numbers
     */
    public ObjectFloatVectorAngular(BufferedReader stream) throws EOFException, IOException, NumberFormatException {
        super(stream);
    }

    //****************** Distance function ******************//
    
    /**
     * Calculates the Angular distance which is a metric.
     * @param obj object to measure the similarity from
     * @param distThreshold distance threshold (not used)
     * @return the "angular" distance between two vectors (angle they enclose)
     */
    @Override
    protected float getDistanceImpl(LocalAbstractObject obj, float distThreshold) {
        float[] objData = ((ObjectFloatVector) obj).data;
        if (objData.length != data.length) {
            throw new IllegalArgumentException("Cannot compute distance on different vector dimensions (" + data.length + ", " + objData.length + ")");
        }

        double productSum = 0f;
        double powASum = 0f;
        double powBSum = 0f;
        for (int i = 0; i < data.length; i++) {
            productSum += data[i] * objData[i];
            powASum += data[i] * data[i];
            powBSum += objData[i] * objData[i];
        }
        float cosineDist = 1f - (float) (Math.abs(productSum) / Math.sqrt(powASum) * Math.sqrt(powBSum));
        return (float)Math.acos(cosineDist);        // possibly normalized it by Math.PI
    }

    //************ BinarySerializable interface ************//
    /**
     * Creates a new instance of {@link ObjectFloatVectorAngular} loaded from
     * binary input buffer.
     *
     * @param input the buffer to read the ObjectFloatVector from
     * @param serializator the serializator used to write objects
     * @throws IOException if there was an I/O error reading from the buffer
     */
    protected ObjectFloatVectorAngular(BinaryInput input, BinarySerializator serializator) throws IOException {
        super(input, serializator);
    }
}
Loading