Created
August 2, 2018 23:06
-
-
Save Engelberg/dc58c52388628fc6e5f0dc78e6eeda0a to your computer and use it in GitHub Desktop.
Comparison Clojure to Java
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public class CoreSubsetObjective implements Objective<SubsetSolution, CoreSubsetData>{ | |
/** | |
* Evaluates the given subset solution using the underlying data, by computing the average | |
* distance between all pairs of selected items. If less than two items are selected, | |
* the evaluation is defined to have a value of 0.0. | |
* | |
* @param solution subset solution | |
* @param data core subset data | |
* @return evaluation with a value set to the average distance between all pairs of selected items; | |
* the value is defined to be 0.0 if less than 2 items are selected | |
*/ | |
@Override | |
public Evaluation evaluate(SubsetSolution solution, CoreSubsetData data) { | |
double value = 0.0; | |
if(solution.getNumSelectedIDs() >= 2){ | |
// at least two items selected: compute average distance | |
int numDist = 0; | |
double sumDist = 0.0; | |
Integer[] selected = new Integer[solution.getNumSelectedIDs()]; | |
solution.getSelectedIDs().toArray(selected); | |
for(int i=0; i<selected.length; i++){ | |
for(int j=i+1; j<selected.length; j++){ | |
sumDist += data.getDistance(selected[i], selected[j]); | |
numDist++; | |
} | |
} | |
value = sumDist/numDist; | |
} | |
return SimpleEvaluation.WITH_VALUE(value); | |
} | |
/** | |
* Always returns <code>false</code> as this objective has to be maximized. | |
* | |
* @return <code>false</code> | |
*/ | |
@Override | |
public boolean isMinimizing() { | |
return false; | |
} | |
} | |
Clojure implementation: | |
(defmacro aget2 [a i j] | |
`(aget ^"[D" (aget ~a ~i) ~j)) | |
(def core-subset-objective | |
(reify Objective | |
(isMinimizing [this] false) | |
(evaluate [this solution data] | |
(SimpleEvaluation/WITH_VALUE | |
(let [n (.getNumSelectedIDs ^SubsetSolution solution) | |
selected (.toArray (.getSelectedIDs ^SubsetSolution solution)) | |
^"[[D" dist (.dist data)] | |
(if (< n 2) 0.0 | |
(loop [acc 0.0 num-pairs 0 i 0 j 1] | |
(cond | |
(>= i n) (/ acc (double num-pairs)) | |
(>= j n) (recur acc num-pairs (inc i) (+ i 2)) | |
:else (recur (+ acc (aget2 dist (aget selected i) (aget selected j))) | |
(inc num-pairs) i (inc j)))))))))) | |
Clojure reify object decompiled into Java | |
// Decompiling class: user$reify__6475$fn__6476 | |
import clojure.lang.*; | |
public final class user$reify__6475$fn__6476 extends AFunction | |
{ | |
Object dist; | |
int n; | |
Object selected; | |
public static final Keyword const__9; | |
public user$reify__6475$fn__6476(final Object dist, final int n, final Object selected) { | |
dist = dist; | |
n = n; | |
selected = selected; | |
} | |
public Object invoke() { | |
double acc = 0.0; | |
long num_pairs = 0L; | |
long i = 0L; | |
long j = 1L; | |
while (i < n) { | |
if (j < n) { | |
final Keyword const__9 = user$reify__6475$fn__6476.const__9; | |
if (const__9 != null) { | |
if (const__9 != Boolean.FALSE) { | |
final double n = acc + ((double[])RT.aget((Object[])dist, RT.intCast(RT.aget((Object[])selected, RT.intCast(i)))))[RT.intCast(RT.aget((Object[])selected, RT.intCast(j)))]; | |
final long inc = Numbers.inc(num_pairs); | |
final long n2 = i; | |
j = Numbers.inc(j); | |
i = n2; | |
num_pairs = inc; | |
acc = n; | |
continue; | |
} | |
} | |
return null; | |
} | |
final double n3 = acc; | |
final long n4 = num_pairs; | |
final long inc2 = Numbers.inc(i); | |
j = Numbers.add(i, 2L); | |
i = inc2; | |
num_pairs = n4; | |
acc = n3; | |
} | |
final double x = acc; | |
final double y = num_pairs; | |
this = null; | |
return Numbers.divide(x, y); | |
} | |
static { | |
const__9 = RT.keyword(null, "else"); | |
} | |
} | |
// Decompiling class: user$reify__6475 | |
import org.jamesframework.core.problems.objectives.*; | |
import org.jamesframework.core.problems.sol.*; | |
import org.jamesframework.core.subset.*; | |
import java.util.*; | |
import clojure.lang.*; | |
import org.jamesframework.core.problems.objectives.evaluations.*; | |
public final class user$reify__6475 implements Objective, IObj | |
{ | |
final IPersistentMap __meta; | |
public static final Object const__2; | |
public user$reify__6475(final IPersistentMap _meta) { | |
__meta = _meta; | |
} | |
public user$reify__6475() { | |
this(null); | |
} | |
public IPersistentMap meta() { | |
return __meta; | |
} | |
public IObj withMeta(final IPersistentMap persistentMap) { | |
return new user$reify__6475(persistentMap); | |
} | |
public Evaluation evaluate(Solution solution, Object data) { | |
final int n = ((SubsetSolution)solution).getNumSelectedIDs(); | |
final Solution solution2 = solution; | |
solution = null; | |
Object selected = ((SubsetSolution)solution2).getSelectedIDs().toArray(); | |
final Object target = data; | |
data = null; | |
Object dist = Reflector.invokeNoArgInstanceMember(target, "dist", false); | |
Object o; | |
if (n < 2L) { | |
o = const__2; | |
} | |
else { | |
final Object o2 = dist; | |
dist = null; | |
final int n2 = n; | |
final Object o3 = selected; | |
selected = null; | |
o = new user$reify__6475$fn__6476(o2, n2, o3).invoke(); | |
} | |
final double doubleCast = RT.doubleCast(o); | |
this = null; | |
return SimpleEvaluation.WITH_VALUE(doubleCast); | |
} | |
public boolean isMinimizing() { | |
return Boolean.FALSE; | |
} | |
static { | |
const__2 = 0.0; | |
} | |
} | |
In my benchmarks, the Java code is approx 3x faster than the Clojure code, even though they are essentially doing the same thing | |
on the same data structures. I find this puzzling. | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment