@@ -0,0 +1,3116 @@
+package com.bbn.nlp.coreference.measures;%0A%0Aimport com.bbn.bue.common.collections.CollectionUtils;%0Aimport com.bbn.bue.common.evaluation.FMeasureInfo;%0Aimport com.bbn.bue.common.evaluation.PrecisionRecallPair;%0Aimport com.google.common.base.Optional;%0Aimport com.google.common.collect.Sets;%0A%0Aimport java.util.List;%0Aimport java.util.Map;%0Aimport java.util.Set;%0A%0A/**%0A * Produces coreference scores according to the MUC metric.%0A *%0A * See Marc Vilain, John Burger, John Aberdeen, Dennis Connolly, and Lynette Hirschman. 1995.%0A * A model-theoretic coreference scoring scheme.%0A * In Proceedings fo the 6th Message Understanding Conference (MUC6).%0A */%0Apublic final class MUCScorer %7B%0A    private MUCScorer() %7B%0A    %7D%0A%0A    public static MUCScorer create() %7B%0A        return new MUCScorer();%0A    %7D%0A%0A    /**%0A     * Returns absent if the score is undefined (e.g. one side is all singletons).%0A     * @param predicted%0A     * @param gold%0A     * @return%0A     */%0A    public Optional%3CFMeasureInfo%3E score(final Iterable%3C? extends Iterable%3C?%3E%3E predicted, final Iterable%3C? extends Iterable%3C?%3E%3E gold) %7B%0A        final List%3CSet%3CObject%3E%3E predictedAsSets = CorefScorerUtils.toSets(predicted);%0A        final List%3CSet%3CObject%3E%3E goldAsSets = CorefScorerUtils.toSets(gold);%0A%0A        final Map%3CObject, Set%3CObject%3E%3E predictedItemToGroup =%0A                CollectionUtils.makeElementsToContainersMap(predictedAsSets);%0A        final Map%3CObject, Set%3CObject%3E%3E goldItemToGroup =%0A                CollectionUtils.makeElementsToContainersMap(goldAsSets);%0A%0A        CorefScorerUtils.checkPartitionsOverSameElements(predictedItemToGroup.keySet(),%0A                goldItemToGroup.keySet());%0A%0A        final Optional%3CFloat%3E recall = mucScoreComponent(goldAsSets, predictedAsSets, predictedItemToGroup);%0A        final Optional%3CFloat%3E precision = mucScoreComponent(predictedAsSets, goldAsSets, goldItemToGroup);%0A%0A        if (recall.isPresent() && precision.isPresent()) %7B%0A            // why are these floats?%0A            return Optional.%3CFMeasureInfo%3Eof(new PrecisionRecallPair(precision.get(), recall.get()));%0A        %7D else %7B%0A            return Optional.absent();%0A        %7D%0A    %7D%0A%0A    private Optional%3CFloat%3E mucScoreComponent(List%3CSet%3CObject%3E%3E leftClustering, List%3CSet%3CObject%3E%3E rightClustering,%0A                                     Map%3CObject, Set%3CObject%3E%3E rightItemToGroup)%0A    %7B%0A        int numerator = 0;%0A        int denominator = 0;%0A%0A        for (final Set%3CObject%3E leftCluster : leftClustering) %7B%0A            final Set%3CSet%3CObject%3E%3E rightClustersThisOneOverlaps = Sets.newHashSet();%0A            for (final Object leftClusterItem : leftCluster) %7B%0A                rightClustersThisOneOverlaps.add(rightItemToGroup.get(leftClusterItem));%0A            %7D%0A%0A            final int overlapSize = rightClustersThisOneOverlaps.size();%0A            final int leftClusterSize = leftCluster.size();%0A%0A            numerator += leftClusterSize - overlapSize;%0A            denominator += leftClusterSize - 1;%0A        %7D%0A%0A        if (denominator %3E 0) %7B%0A            return Optional.of(((float)numerator)/denominator);%0A        %7D else %7B%0A            return Optional.absent();%0A        %7D%0A    %7D%0A%7D%0A

Add MUC scorer