/* * Copyright (C) 2009 lichtflut Forschungs- und Entwicklungsgesellschaft mbH * * 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 de.lichtflut.infra.data; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import java.util.Set; /** * Finds a path in a {@link ProbabilityMatrix}. * * Created: 11.10.2008 * * @author Oliver Tigges */ public class PathFinder<K, V> { private final List<ProbabilityMatrixPath<K,V>> paths = new ArrayList<ProbabilityMatrixPath<K,V>>(); private final MultiMap<K, Probable<V>> map; //------------------------------------------------------ public PathFinder(MultiMap<K, Probable<V>> map) { this.map = map; } //----------------------------------------------------- /** * Find all paths in the matrix */ public List<ProbabilityMatrixPath<K,V>> findAllPaths(){ paths.add(new ProbabilityMatrixPath<K,V>()); Set<K> keys = map.keySet(); for (K key : keys) { append(key); } return paths; } //------------------------------------------------------ /** * append the node for given key to result list * @param key * @param paths * @return */ private void append(K key) { Set<Probable<V>> possibles = map.getValues(key); if (possibles.isEmpty()){ // no value for key } else if (possibles.size() == 1){ // exactly one value for key Probable<V> pv = possibles.iterator().next(); // appending this element to all paths appendToPaths(key, pv, paths); } else { // many values for keys --> lists have to be forked int size = possibles.size(); List<ProbabilityMatrixPath<K,V>> origs = new ArrayList<ProbabilityMatrixPath<K,V>>(paths); // iterate over copy, because original will be modified for (ProbabilityMatrixPath<K,V> current : origs) { List<ProbabilityMatrixPath<K,V>> altPahts = cloneToSize(current, size); Iterator<Probable<V>> valueIterator = possibles.iterator(); for (int i=0; i < size; i++){ Probable<V> pv = valueIterator.next(); ProbabilityMatrixPath<K,V> path = altPahts.get(i); if (!path.contains(pv.getValue())){ path.addPathElement(key, pv.getValue(), pv.getProbability()); } else { path.invalidate(); } } } } } private void appendToPaths(K key, Probable<V> pv, List<ProbabilityMatrixPath<K,V>> paths) { for (ProbabilityMatrixPath<K,V> path : paths) { if (!path.contains(pv.getValue())){ path.addPathElement(key, pv.getValue(), pv.getProbability()); } else { path.invalidate(); } } } /** * clones the given path (size -1) times to have "size" instances * @param original * @param size * @return */ private List<ProbabilityMatrixPath<K,V>> cloneToSize(ProbabilityMatrixPath<K,V> original, int size){ List<ProbabilityMatrixPath<K,V>> result = new ArrayList<ProbabilityMatrixPath<K,V>>(size); result.add(original); for (int i = 1; i <= size -1; i++){ ProbabilityMatrixPath<K,V> clone = original.copy(); paths.add(clone); result.add(clone); } return result; } }