Skip to content

Instantly share code, notes, and snippets.

@Engelberg
Created August 2, 2018 23:06
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Engelberg/dc58c52388628fc6e5f0dc78e6eeda0a to your computer and use it in GitHub Desktop.
Save Engelberg/dc58c52388628fc6e5f0dc78e6eeda0a to your computer and use it in GitHub Desktop.
Comparison Clojure to Java
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