/******************************************************************************* * Copyright 2014 Felipe Takiyama * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. ******************************************************************************/ package br.usp.poli.takiyama.common; import java.util.Collection; import java.util.HashSet; import java.util.Iterator; import java.util.Set; import br.usp.poli.takiyama.prv.Substitution; import br.usp.poli.takiyama.utils.Sets; /** * Standard implementation of {@link Distribution}. This implementation is a * immutable set of {@link Parfactor}s. * * @author Felipe Takiyama * */ public final class StdDistribution implements Distribution { private Set<Parfactor> pSet; /* ************************************************************************ * Constructors * ************************************************************************/ /** * Creates an empty distribution with the specified initial capacity. * @param capacity The initial capacity */ private StdDistribution(int capacity) { this.pSet = new HashSet<Parfactor>(capacity); } /** * Creates a distribution with the elements of the specified set. * @param p A set of parfactors whose elements will compose this * distribution */ private StdDistribution(Set<Parfactor> p) { pSet = new HashSet<Parfactor>(Math.max((int) (p.size()/.75f) + 1, 16)); pSet.addAll(p); } /* ************************************************************************ * Static factories * ************************************************************************/ /** * Creates an empty distribution */ public static Distribution of() { return new StdDistribution(0); } /** * Creates a distribution with one parfactor * @param p1 A parfactor * @throws NullPointerException If the specified parfators is <code>null</code>. */ public static Distribution of(Parfactor p1) throws NullPointerException { if (p1 == null) { throw new NullPointerException(); } Set<Parfactor> set = new HashSet<Parfactor>(2); set.add(p1); return new StdDistribution(set); } /** * Creates a distribution with two parfactors * @param p1 The first parfactor to put in the distribution * @param p2 The second parfactor to put in the distribution * @throws NullPointerException If any of the specified parfators is * <code>null</code>. */ public static Distribution of(Parfactor p1, Parfactor p2) throws NullPointerException { if (p1 == null || p2 == null) { throw new NullPointerException(); } Set<Parfactor> set = new HashSet<Parfactor>(2); set.add(p1); set.add(p2); return new StdDistribution(set); } /** * Returns a distribution with the specified parfactors. * * @param parfactors An array of parfactors. * @throws NullPointerException If any of the specified parfators is * <code>null</code>. */ public static Distribution of(Parfactor ... parfactors) throws NullPointerException { Set<Parfactor> set = new HashSet<Parfactor>((int) (parfactors.length / 0.75)); for (Parfactor p : parfactors) { if (p == null) { throw new NullPointerException(); } else { set.add(p); } } return new StdDistribution(set); } /** * Creates a distribution with the specified collection of parfactors * @param c A collection of parfactors * @throws NullPointerException If the specified Collection contains a * <code>null</code> element. */ public static Distribution of(Collection<? extends Parfactor> c) throws NullPointerException { if (c.contains(null)) { throw new NullPointerException(); } StdDistribution dist = new StdDistribution(Math.max((int) (c.size()/.75f) + 1, 16)); dist.addAll(c); return dist; } /** * Creates a distribution that has the same elements as the specified * distribution. The order in which the elements are put in the new * distribution is not necessarily the same as the specified distribution. * * @param d The distribution to "copy" * @return A distribution with the same elements as the specified * distribution. * @throws NullPointerException If the specified Distribution contains a * <code>null</code> element. */ public static Distribution of(Distribution d) throws NullPointerException { if (d.contains(null)) { throw new NullPointerException(); } StdDistribution dist = new StdDistribution(Math.max((int) (d.size()/.75f) + 1, 16)); dist.addAll(d.toSet()); return dist; } /* ************************************************************************ * Auxiliary methods * ************************************************************************/ private void addAll(Collection<? extends Parfactor> c) { pSet.addAll(c); } /* ************************************************************************ * Interface methods * ************************************************************************/ @Override public Distribution add(Parfactor p) { Set<Parfactor> newSet = new HashSet<Parfactor>(pSet); newSet.add(p); return new StdDistribution(newSet); } @Override public Distribution addAll(Distribution d) { return new StdDistribution(Sets.union(d.toSet(), pSet)); } @Override public boolean contains(Object o) throws NullPointerException { return pSet.contains(o); } @Override public boolean containsAll(Distribution d) { return pSet.containsAll(d.toSet()); } @Override public boolean isEmpty() { return pSet.isEmpty(); } @Override public Iterator<Parfactor> iterator() { return pSet.iterator(); } @Override public int size() { return pSet.size(); } @Override public Set<Parfactor> toSet() { return new HashSet<Parfactor>(pSet); } @Override public Distribution apply(Substitution s) { return new StdDistribution(Sets.apply(s, pSet)); } /* ************************************************************************ * hashCode, equals and toStrings * ************************************************************************/ @Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + ((pSet == null) ? 0 : pSet.hashCode()); return result; } @Override public boolean equals(Object obj) { if (this == obj) { return true; } if (obj == null) { return false; } if (!(obj instanceof StdDistribution)) { return false; } StdDistribution other = (StdDistribution) obj; if (pSet == null) { if (other.pSet != null) { return false; } } else if (!pSet.equals(other.pSet)) { return false; } return true; } @Override public String toString() { return pSet.toString(); } }