code: @Override
  	public double calculateExpectedDisagreement() {
  		ensureDistanceFunction();
  		if (coincidenceMatrix == null) {
              coincidenceMatrix = CodingAnnotationStudy.countCategoryCoincidence(study);
          }
  
          if (study.getCategoryCount() <= 1) {
              throw new InsufficientDataException("An annotation study needs at least two different categories; otherwise there is no decision for the raters to agree on.");
          }
  
          double n = 0.0;
  		Map<Object, Double> marginals = new HashMap<Object, Double>();
  		for (Entry<Object, Map<Object, Double>> cat1 : coincidenceMatrix.entrySet()) {
  			double n_c = 0.0;
  			for (Entry<Object, Double> cat2 : cat1.getValue().entrySet()) {
                  n_c += cat2.getValue();
              }
  			marginals.put(cat1.getKey(), n_c);
  			n += n_c;
  		}
  
  		double result = 0.0;
  		for (Entry<Object, Double> cat1 : marginals.entrySet()) {
              for (Entry<Object, Double> cat2 : marginals.entrySet()) {
                  result += cat1.getValue() * cat2.getValue()
  						* distanceFunction.measureDistance(study, cat1.getKey(), cat2.getKey());
              }
          }
  		result /= n * (n - 1.0);
  		return result;
  	}
docs: Calculates the expected inter-rater agreement using the defined
  distance function to infer the assumed probability distribution.
  @throws NullPointerException if the annotation study is null.
  @throws ArithmeticException if there are no items or raters in the
  annotation study.