Commit 92fa854d authored by david's avatar david
Browse files

* EMD implementation

parent bc7a0284
Loading
Loading
Loading
Loading
+67 −67
Original line number Diff line number Diff line
package messif.objects.impl;

import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.Vector;


/**
@@ -71,20 +71,18 @@ class Edge3 {
class MinCostFlow {

    int numNodes;
    Vector<Integer> nodesToQ;
    //List<Integer> nodesToQ;
    int nodesToQ [];

    // e - supply(positive) and demand(negative).
    // c[i] - edges that goes from node i. first is the second nod
    // x - the flow is returned in it
    long compute(Vector<Long> e, Vector<List<Edge>> c, Vector<List<Edge0>> x) {
        assert (e.size() == c.size());
    long compute(long [] e, List<List<Edge>> c, List<List<Edge0>> x) {
        assert (e.length == c.size());
        assert (x.size() == c.size());

        numNodes = e.size();
        nodesToQ = new Vector<Integer>();
        for (int i = 0; i < numNodes; i++) {
            nodesToQ.add(0);
        }
        numNodes = e.length;
        nodesToQ = new int[numNodes];

        // init flow
        for (int from = 0; from < numNodes; ++from) {
@@ -96,7 +94,7 @@ class MinCostFlow {

        // reduced costs for forward edges (c[i,j]-pi[i]+pi[j])
        // Note that for forward edges the residual capacity is infinity
        Vector<List<Edge1>> rCostForward = new Vector<List<Edge1>>();
        List<List<Edge1>> rCostForward = new ArrayList<>();
        for (int i = 0; i < numNodes; i++) {
            rCostForward.add(new LinkedList<Edge1>());
        }
@@ -110,7 +108,7 @@ class MinCostFlow {
        // (c[j,i]-pi[j]+pi[i])
        // Since the flow at the beginning is 0, the residual capacity is
        // also zero
        Vector<List<Edge2>> rCostCapBackward = new Vector<List<Edge2>>();
        List<List<Edge2>> rCostCapBackward = new ArrayList<>();
        for (int i = 0; i < numNodes; i++) {
            rCostCapBackward.add(new LinkedList<Edge2>());
        }
@@ -125,26 +123,28 @@ class MinCostFlow {
        // demand,supply
        long U = 0;
        for (int i = 0; i < numNodes; i++) {
            if (e.get(i) > U)
                U = e.get(i);
        }
        long delta = (long) (Math.pow(2.0,
                Math.ceil(Math.log((double) (U)) / Math.log(2.0))));

        Vector<Long> d = new Vector<Long>();
        Vector<Integer> prev = new Vector<Integer>();
        for (int i = 0; i < numNodes; i++) {
            d.add(0l);
            prev.add(0);
        }
        delta = 1;
            if (e[i] > U)
                U = e[i];
        }
//        long delta = (long) (Math.pow(2.0,
//                Math.ceil(Math.log((float) (U)) / Math.log(2.0))));

//        List<Long> d = new List<Long>();
//        List<Integer> prev = new List<Integer>();
//        for (int i = 0; i < numNodes; i++) {
//            d.add(0l);
//            prev.add(0);
//        }
        long [] d = new long [numNodes];
        int [] prev = new int [numNodes];
        long delta;
        while (true) { // until we break when S or T is empty
            long maxSupply = 0;
            int k = 0;
            for (int i = 0; i < numNodes; i++) {
                if (e.get(i) > 0) {
                    if (maxSupply < e.get(i)) {
                        maxSupply = e.get(i);
                if (e[i] > 0) {
                    if (maxSupply < e[i]) {
                        maxSupply = e[i];
                        k = i;
                    }
                }
@@ -162,7 +162,7 @@ class MinCostFlow {
            // if (-e[l]<delta) delta= e[k];
            int to = l[0];
            do {
                int from = prev.get(to);
                int from = prev[to];
                assert (from != to);

                // residual
@@ -182,7 +182,7 @@ class MinCostFlow {
            // augment delta flow from k to l (backwards actually...)
            to = l[0];
            do {
                int from = prev.get(to);
                int from = prev[to];
                assert (from != to);

                // TODO - might do here O(n) can be done in O(1)
@@ -211,8 +211,8 @@ class MinCostFlow {
                }

                // update e
                e.set(to, e.get(to) + delta);
                e.set(from, e.get(from) - delta);
                e[to] = e[to] + delta;
                e[from] = e[from] - delta;

                to = from;
            } while (to != k);
@@ -228,45 +228,45 @@ class MinCostFlow {
        return dist;
    }

    void computeShortestPath(Vector<Long> d, Vector<Integer> prev,
            int from, Vector<List<Edge1>> costForward,
            Vector<List<Edge2>> costBackward, Vector<Long> e, int[] l) {
    void computeShortestPath(long [] d, int [] prev,
            int from, List<List<Edge1>> costForward,
            List<List<Edge2>> costBackward, long [] e, int[] l) {
        // Making heap (all inf except 0, so we are saving comparisons...)
        Vector<Edge3> Q = new Vector<Edge3>();
        List<Edge3> Q = new ArrayList<>(numNodes);
        for (int i = 0; i < numNodes; i++) {
            Q.add(new Edge3());
        }

        Q.get(0)._to = from;
        nodesToQ.set(from, 0);
        nodesToQ[from] = 0;
        Q.get(0)._dist = 0;

        int j = 1;
        // TODO: both of these into a function?
        for (int i = 0; i < from; ++i) {
            Q.get(j)._to = i;
            nodesToQ.set(i, j);
            nodesToQ[i] = j;
            Q.get(j)._dist = Long.MAX_VALUE;
            j++;
        }

        for (int i = from + 1; i < numNodes; i++) {
            Q.get(j)._to = i;
            nodesToQ.set(i, j);
            nodesToQ[i] = j;
            Q.get(j)._dist = Long.MAX_VALUE;
            j++;
        }

        Vector<Boolean> finalNodesFlg = new Vector<Boolean>();
        for (int i = 0; i < numNodes; i++) {
            finalNodesFlg.add(false);
        }
        boolean [] finalNodesFlg = new boolean [numNodes];
//        for (int i = 0; i < numNodes; i++) {
//            finalNodesFlg.add(false);
//        }
        do {
            int u = Q.get(0)._to;

            d.set(u, Q.get(0)._dist); // final distance
            finalNodesFlg.set(u, true);
            if (e.get(u) < 0) {
            d[u] = Q.get(0)._dist; // final distance
            finalNodesFlg[u] = true;
            if (e[u] < 0) {
                l[0] = u;
                break;
            }
@@ -276,23 +276,23 @@ class MinCostFlow {
            // neighbors of u
            for (Edge1 it : costForward.get(u)) {
                assert (it._reduced_cost >= 0);
                long alt = d.get(u) + it._reduced_cost;
                long alt = d[u] + it._reduced_cost;
                int v = it._to;
                if ((nodesToQ.get(v) < Q.size())
                        && (alt < Q.get(nodesToQ.get(v))._dist)) {
                if ((nodesToQ[v] < Q.size())
                        && (alt < Q.get(nodesToQ[v])._dist)) {
                    heapDecreaseKey(Q, nodesToQ, v, alt);
                    prev.set(v, u);
                    prev[v] = u;
                }
            }
            for (Edge2 it : costBackward.get(u)) {
                if (it._residual_capacity > 0) {
                    assert (it._reduced_cost >= 0);
                    long alt = d.get(u) + it._reduced_cost;
                    long alt = d[u] + it._reduced_cost;
                    int v = it._to;
                    if ((nodesToQ.get(v) < Q.size())
                            && (alt < Q.get(nodesToQ.get(v))._dist)) {
                    if ((nodesToQ[v] < Q.size())
                            && (alt < Q.get(nodesToQ[v])._dist)) {
                        heapDecreaseKey(Q, nodesToQ, v, alt);
                        prev.set(v, u);
                        prev[v] = u;
                    }
                }
            }
@@ -301,11 +301,11 @@ class MinCostFlow {

        for (int _from = 0; _from < numNodes; ++_from) {
            for (Edge1 it : costForward.get(_from)) {
                if (finalNodesFlg.get(_from)) {
                    it._reduced_cost += d.get(_from) - d.get(l[0]);
                if (finalNodesFlg[_from]) {
                    it._reduced_cost += d[_from] - d[l[0]];
                }
                if (finalNodesFlg.get(it._to)) {
                    it._reduced_cost -= d.get(it._to) - d.get(l[0]);
                if (finalNodesFlg[it._to]) {
                    it._reduced_cost -= d[it._to] - d[l[0]];
                }
            }
        }
@@ -314,19 +314,19 @@ class MinCostFlow {
        // (c[j,i]-pi[j]+pi[i])
        for (int _from = 0; _from < numNodes; ++_from) {
            for (Edge2 it : costBackward.get(_from)) {
                if (finalNodesFlg.get(_from)) {
                    it._reduced_cost += d.get(_from) - d.get(l[0]);
                if (finalNodesFlg[_from]) {
                    it._reduced_cost += d[_from] - d[l[0]];
                }
                if (finalNodesFlg.get(it._to)) {
                    it._reduced_cost -= d.get(it._to) - d.get(l[0]);
                if (finalNodesFlg[it._to]) {
                    it._reduced_cost -= d[it._to] - d[l[0]];
                }
            }
        }
    }

    void heapDecreaseKey(Vector<Edge3> Q, Vector<Integer> nodes_to_Q,
    void heapDecreaseKey(List<Edge3> Q, int [] nodes_to_Q,
            int v, long alt) {
        int i = nodes_to_Q.get(v);
        int i = nodes_to_Q[v];
        Q.get(i)._dist = alt;
        while (i > 0 && Q.get(PARENT(i))._dist > Q.get(i)._dist) {
            swapHeap(Q, nodes_to_Q, i, PARENT(i));
@@ -334,13 +334,13 @@ class MinCostFlow {
        }
    }

    void heapRemoveFirst(Vector<Edge3> Q, Vector<Integer> nodes_to_Q) {
    void heapRemoveFirst(List<Edge3> Q, int [] nodes_to_Q) {
        swapHeap(Q, nodes_to_Q, 0, Q.size() - 1);
        Q.remove(Q.size() - 1);
        heapify(Q, nodes_to_Q, 0);
    }

    void heapify(Vector<Edge3> Q, Vector<Integer> nodes_to_Q, int i) {
    void heapify(List<Edge3> Q, int [] nodes_to_Q, int i) {
        do {
            // TODO: change to loop
            int l = LEFT(i);
@@ -364,12 +364,12 @@ class MinCostFlow {
        } while (true);
    }

    void swapHeap(Vector<Edge3> Q, Vector<Integer> nodesToQ, int i, int j) {
    void swapHeap(List<Edge3> Q, int [] nodesToQ, int i, int j) {
        Edge3 tmp = Q.get(i);
        Q.set(i, Q.get(j));
        Q.set(j, tmp);
        nodesToQ.set(Q.get(j)._to, j);
        nodesToQ.set(Q.get(i)._to, i);
        nodesToQ[Q.get(j)._to] = j;
        nodesToQ[Q.get(i)._to] = i;
    }

    int LEFT(int i) {
+105 −123
Original line number Diff line number Diff line
@@ -14,18 +14,20 @@

package messif.objects.impl;

import java.util.HashSet;
import gnu.trove.list.TIntList;
import gnu.trove.list.array.TIntArrayList;
import gnu.trove.set.TIntSet;
import gnu.trove.set.hash.TIntHashSet;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;
import java.util.Vector;

/**
 * @author Telmo Menezes (telmo@telmomenezes.com)
 * @author Ofir Pele
 *
 */
public class JFastEMD {
public class EarthMoverDistance {
    /**
     * This interface is similar to Rubner's interface. See:
     * http://www.cs.duke.edu/~tomasi/software/emd.htm
@@ -50,36 +52,29 @@ public class JFastEMD {
     *
     * If you use this code, please cite the papers.
     */
    static public double distance(Signature signature1, Signature signature2, double extraMassPenalty) {
    static public float distance(ObjectSignatureTemporary signature1, ObjectSignatureTemporary signature2, float extraMassPenalty) {

        Vector<Double> P = new Vector<Double>();
        Vector<Double> Q = new Vector<Double>();
        for (int i = 0; i < signature1.getNumberOfFeatures() + signature2.getNumberOfFeatures(); i++) {
            P.add(0.0);
            Q.add(0.0);
        }
        for (int i = 0; i < signature1.getNumberOfFeatures(); i++) {
            P.set(i, signature1.getWeights()[i]);
        }
        for (int j = 0; j < signature2.getNumberOfFeatures(); j++) {
            Q.set(j + signature1.getNumberOfFeatures(), signature2.getWeights()[j]);
        }
        int size1 = signature1.getNumberOfFeatures();
        int size2 = signature2.getNumberOfFeatures();

        Vector<Vector<Double>> C = new Vector<Vector<Double>>();
        for (int i = 0; i < P.size(); i++) {
            Vector<Double> vec = new Vector<Double>();
            for (int j = 0; j < P.size(); j++) {
                vec.add(0.0);
            }
            C.add(vec);
        float [] P = new float [size1 + size2];
        float [] Q = new float [size1 + size2];
        
        System.arraycopy(signature1.getWeights(), 0, P, 0, size1);
        System.arraycopy(signature2.getWeights(), 0, Q, size1, size2);

        float [] [] C = new float [size1+size2] [];
        for (int i = 0; i < size1 + size2; i++) {
            C[i] = new float [size1+size2];
        }
        for (int i = 0; i < signature1.getNumberOfFeatures(); i++) {
            for (int j = 0; j < signature2.getNumberOfFeatures(); j++) {
                double dist = signature1.getFeatures()[i]
                        .groundDist(signature2.getFeatures()[j]);
        
        for (int i = 0; i < size1; i++) {
            for (int j = 0; j < size2; j++) {
                float dist = signature1.getFeatures()[i]
                        .featureDistance(signature2.getFeatures()[j]);
                assert (dist >= 0);
                C.get(i).set(j + signature1.getNumberOfFeatures(), dist);
                C.get(j + signature1.getNumberOfFeatures()).set(i, dist);
                C[i][j+size1] = dist;
                C[j+size1][i] = dist;
            }
        }

@@ -87,23 +82,26 @@ public class JFastEMD {
    }
    

    static private long emdHatImplLongLongInt(Vector<Long> Pc, Vector<Long> Qc,
            Vector<Vector<Long>> C, long extraMassPenalty) {
//    static private long emdHatImplLongLongInt(Vector<Long> Pc, Vector<Long> Qc,
//            Vector<Vector<Long>> C, long extraMassPenalty) {
    static private long emdHatImplLongLongInt(long [] Pc, long [] Qc, long [] [] C, long extraMassPenalty) {

        int N = Pc.size();
        assert (Qc.size() == N);
        int N = Pc.length;
        assert (Qc.length == N);

        // Ensuring that the supplier - P, have more mass.
        // Note that we assume here that C is symmetric
        Vector<Long> P;
        Vector<Long> Q;
        //Vector<Long> P;
        //Vector<Long> Q;
        long [] P, Q;
        long absDiffSumPSumQ;
        long sumP = 0;
        long sumQ = 0;
        for (int i = 0; i < N; i++)
            sumP += Pc.get(i);
            sumP += Pc[i];
        for (int i = 0; i < N; i++)
            sumQ += Qc.get(i);
            sumQ += Qc[i];
        
        if (sumQ > sumP) {
            P = Qc;
            Q = Pc;
@@ -115,18 +113,15 @@ public class JFastEMD {
        }

        // creating the b vector that contains all vertexes
        Vector<Long> b = new Vector<Long>();
        for (int i = 0; i < 2 * N + 2; i++) {
            b.add(0l);
        }
        //Vector<Long> b = new Vector<Long>();
        long [] b = new long [2 * N + 2];
//        for (int i = 0; i < 2 * N + 2; i++) {
//            b.add(0l);
//        }
        int THRESHOLD_NODE = 2 * N;
        int ARTIFICIAL_NODE = 2 * N + 1; // need to be last !
        for (int i = 0; i < N; i++) {
            b.set(i, P.get(i));
        }
        for (int i = N; i < 2 * N; i++) {
            b.set(i, Q.get(i - N));
        }
        System.arraycopy(P, 0, b, 0, N);
        System.arraycopy(Q, 0, b, N, N);

        // remark*) I put here a deficit of the extra mass, as mass that flows
        // to the threshold node
@@ -136,50 +131,39 @@ public class JFastEMD {
        // threshold and outgoing
        // edges had the cost of zero)
        // This also makes sum of b zero.
        b.set(THRESHOLD_NODE, -absDiffSumPSumQ);
        b.set(ARTIFICIAL_NODE, 0l);
        b[THRESHOLD_NODE] =  -absDiffSumPSumQ;
        //b.set(ARTIFICIAL_NODE = 0l;

        long maxC = 0;
        for (int i = 0; i < N; i++) {
            for (int j = 0; j < N; j++) {
                assert (C.get(i).get(j) >= 0);
                if (C.get(i).get(j) > maxC)
                    maxC = C.get(i).get(j);
//                assert (C[i][j] >= 0);
                if (C[i][j] > maxC)
                    maxC = C[i][j];
            }
        }
        if (extraMassPenalty == -1)
            extraMassPenalty = maxC;

        Set<Integer> sourcesThatFlowNotOnlyToThresh = new HashSet<Integer>();
        Set<Integer> sinksThatGetFlowNotOnlyFromThresh = new HashSet<Integer>();
        //Set<Integer> sourcesThatFlowNotOnlyToThresh = new HashSet<Integer>();
        //Set<Integer> sinksThatGetFlowNotOnlyFromThresh = new HashSet<Integer>();
        TIntSet sourcesThatFlowNotOnlyToThresh = new TIntHashSet();
        TIntSet sinksThatGetFlowNotOnlyFromThresh = new TIntHashSet();
        long preFlowCost = 0;

        // regular edges between sinks and sources without threshold edges
        Vector<List<Edge>> c = new Vector<List<Edge>>();
        for (int i = 0; i < b.size(); i++) {
        List<List<Edge>> c = new ArrayList<>();
        for (int i = 0; i < b.length; i++) {
            c.add(new LinkedList<Edge>());
        }
        for (int i = 0; i < N; i++) {
            if (b.get(i) == 0)
            if (b[i] == 0)
                continue;
            for (int j = 0; j < N; j++) {
                if (b.get(j + N) == 0)
                    continue;
                if (C.get(i).get(j) == maxC)
                if (b[j + N] == 0 || C[i][j] == maxC)
                    continue;
                c.get(i).add(new Edge(j + N, C.get(i).get(j)));
            }
        }

                c.get(i).add(new Edge(j + N, C[i][j]));
                // checking which are not isolated
        for (int i = 0; i < N; i++) {
            if (b.get(i) == 0)
                continue;
            for (int j = 0; j < N; j++) {
                if (b.get(j + N) == 0)
                    continue;
                if (C.get(i).get(j) == maxC)
                    continue;
                sourcesThatFlowNotOnlyToThresh.add(i);
                sinksThatGetFlowNotOnlyFromThresh.add(j + N);
            }
@@ -187,7 +171,7 @@ public class JFastEMD {

        // converting all sinks to negative
        for (int i = N; i < 2 * N; i++) {
            b.set(i, -b.get(i));
            b[i] = -b[i];
        }

        // add edges from/to threshold node,
@@ -214,14 +198,17 @@ public class JFastEMD {
        // Note here it should be vector<int> and not vector<int>
        // as I'm using -1 as a special flag !!!
        int REMOVE_NODE_FLAG = -1;
        Vector<Integer> nodesNewNames = new Vector<Integer>();
        Vector<Integer> nodesOldNames = new Vector<Integer>();
        for (int i = 0; i < b.size(); i++) {
        //Vector<Integer> nodesNewNames = new Vector<Integer>();
        //Vector<Integer> nodesOldNames = new Vector<Integer>();
        TIntList nodesNewNames = new TIntArrayList(b.length);
        TIntList nodesOldNames = new TIntArrayList(b.length);
        
        for (int i = 0; i < b.length; i++) {
            nodesNewNames.add(REMOVE_NODE_FLAG);
            nodesOldNames.add(0);
        }
        for (int i = 0; i < N * 2; i++) {
            if (b.get(i) != 0) {
            if (b[i] != 0) {
                if (sourcesThatFlowNotOnlyToThresh.contains(i)
                        || sinksThatGetFlowNotOnlyFromThresh.contains(i)) {
                    nodesNewNames.set(i, currentNodeName);
@@ -229,9 +216,9 @@ public class JFastEMD {
                    currentNodeName++;
                } else {
                    if (i >= N) {
                        preFlowCost -= (b.get(i) * maxC);
                        preFlowCost -= (b[i] * maxC);
                    }
                    b.set(THRESHOLD_NODE, b.get(THRESHOLD_NODE) + b.get(i)); // add mass(i<N) or deficit (i>=N)
                    b[THRESHOLD_NODE] =  b[THRESHOLD_NODE] + b[i]; // add mass(i<N) or deficit (i>=N)
                }
            }
        }
@@ -242,20 +229,21 @@ public class JFastEMD {
        nodesOldNames.add(ARTIFICIAL_NODE);
        currentNodeName++;

        Vector<Long> bb = new Vector<Long>();
        for (int i = 0; i < currentNodeName; i++) {
            bb.add(0l);
        }
//        Vector<Long> bb = new Vector<Long>();
//        for (int i = 0; i < currentNodeName; i++) {
//            bb.add(0l);
//        }
        long [] bb = new long [currentNodeName];
        int j = 0;
        for (int i = 0; i < b.size(); i++) {
        for (int i = 0; i < b.length; i++) {
            if (nodesNewNames.get(i) != REMOVE_NODE_FLAG) {
                bb.set(j, b.get(i));
                bb[j] = b[i];
                j++;
            }
        }

        Vector<List<Edge>> cc = new Vector<List<Edge>>();
        for (int i = 0; i < bb.size(); i++) {
        List<List<Edge>> cc = new ArrayList<>(currentNodeName);
        for (int i = 0; i < currentNodeName; i++) {
            cc.add(new LinkedList<Edge>());
        }
        for (int i = 0; i < c.size(); i++) {
@@ -273,8 +261,8 @@ public class JFastEMD {

        long myDist;

        Vector<List<Edge0>> flows = new Vector<List<Edge0>>(bb.size());
        for (int i = 0; i < bb.size(); i++) {
        List<List<Edge0>> flows = new ArrayList<>(bb.length);
        for (int i = 0; i < bb.length; i++) {
            flows.add(new LinkedList<Edge0>());
        }

@@ -287,60 +275,54 @@ public class JFastEMD {
        return myDist;
    }

    static private double emdHat(Vector<Double> P, Vector<Double> Q, Vector<Vector<Double>> C,
            double extraMassPenalty) {
    //static private float emdHat(Vector<Double> P, Vector<Double> Q, Vector<Vector<Double>> C,
    static private float emdHat(float [] P, float [] Q, float [] [] C,
            float extraMassPenalty) {

        // This condition should hold:
        // ( 2^(sizeof(CONVERT_TO_T*8)) >= ( MULT_FACTOR^2 )
        // Note that it can be problematic to check it because
        // of overflow problems. I simply checked it with Linux calc
        // which has arbitrary precision.
        double MULT_FACTOR = 1000000;
        float MULT_FACTOR = 1000000;

        // Constructing the input
        int N = P.size();
        Vector<Long> iP = new Vector<Long>();
        Vector<Long> iQ = new Vector<Long>();
        Vector<Vector<Long>> iC = new Vector<Vector<Long>>();
        int N = P.length;
        long [] iP = new long [N];
        long [] iQ = new long [N];
        long [] [] iC = new long [N] [];
        for (int i = 0; i < N; i++) {
            iP.add(0l);
            iQ.add(0l);
            Vector<Long> vec = new Vector<Long>();
            for (int j = 0; j < N; j++) {
                vec.add(0l);
            }
            iC.add(vec);
            iC[i] = new long [N];
        }

        // Converting to CONVERT_TO_T
        double sumP = 0.0;
        double sumQ = 0.0;
        double maxC = C.get(0).get(0);
        float sumP = 0f;
        float sumQ = 0f;
        float maxC = C[0][0];
        for (int i = 0; i < N; i++) {
            sumP += P.get(i);
            sumQ += Q.get(i);
            sumP += P[i];
            sumQ += Q[i];
            for (int j = 0; j < N; j++) {
                if (C.get(i).get(j) > maxC)
                    maxC = C.get(i).get(j);
                if (C[i][j] > maxC)
                    maxC = C[i][j];
            }
        }
        double minSum = Math.min(sumP, sumQ);
        double maxSum = Math.max(sumP, sumQ);
        double PQnormFactor = MULT_FACTOR / maxSum;
        double CnormFactor = MULT_FACTOR / maxC;
        float minSum = Math.min(sumP, sumQ);
        float maxSum = Math.max(sumP, sumQ);
        float PQnormFactor = MULT_FACTOR / maxSum;
        float CnormFactor = MULT_FACTOR / maxC;
        for (int i = 0; i < N; i++) {
            iP.set(i, (long) (Math.floor(P.get(i) * PQnormFactor + 0.5)));
            iQ.set(i, (long) (Math.floor(Q.get(i) * PQnormFactor + 0.5)));
            iP[i] = (long) (Math.floor(P[i] * PQnormFactor + 0.5));
            iQ[i] = (long) (Math.floor(Q[i] * PQnormFactor + 0.5));
            for (int j = 0; j < N; j++) {
                iC.get(i)
                        .set(j,
                                (long) (Math.floor(C.get(i).get(j)
                                        * CnormFactor + 0.5)));
                iC[i][j] =
                                (long) (Math.floor(C[i][j]
                                        * CnormFactor + 0.5));
            }
        }

        // computing distance without extra mass penalty
        double dist = emdHatImplLongLongInt(iP, iQ, iC, 0);
        float dist = emdHatImplLongLongInt(iP, iQ, iC, 0);
        // unnormalize
        dist = dist / PQnormFactor;
        dist = dist / CnormFactor;
+0 −5
Original line number Diff line number Diff line
package messif.objects.impl;

public interface Feature {
    public double groundDist(Feature f);
}
 No newline at end of file
+61 −0

File added.

Preview size limit exceeded, changes collapsed.

+12 −0
Original line number Diff line number Diff line
package messif.objects.impl;

import java.io.IOException;
import java.io.OutputStream;

public interface ObjectFeatureTemporary {
    
    public float featureDistance(ObjectFeatureTemporary f);
    
    public void writeData(OutputStream stream) throws IOException;
    
}
 No newline at end of file
Loading