All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.tweetyproject.commons.util.MapTools Maven / Gradle / Ivy

The newest version!
/*
 *  This file is part of "TweetyProject", a collection of Java libraries for
 *  logical aspects of artificial intelligence and knowledge representation.
 *
 *  TweetyProject is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU Lesser General Public License version 3 as
 *  published by the Free Software Foundation.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public License
 *  along with this program. If not, see .
 *
 *  Copyright 2016 The TweetyProject Team 
 */
package org.tweetyproject.commons.util;

import java.util.*;

/**
 * This class provides some utility functions for maps.
 * @author Matthias Thimm
 *
 * @param  Domain class of the maps
 * @param  Range class of the maps
 */
public class MapTools {

	/** Constructor*/
	public MapTools(){

	}
	/**
	 * Computes the complete set of maps from E to F such that the following
	 * condition holds. For every map "m" in the result the set m.keySet()
	 * is equal to the union of all sets S with S in relations.keySet() and each
	 * element "e" in m.keySet() is mapped to an element "f" such that "f" in
	 * relations.get(S) with "e" in S. For example the map:
* {a,b} => {1,2}
* {c,d} => {3}
* {f} => {4,5}
* yields the set of maps:
* a=>1, b=>1, c=>3, d=>3, f=>4
* a=>1, b=>1, c=>3, d=>3, f=>5
* a=>1, b=>2, c=>3, d=>3, f=>4
* a=>1, b=>2, c=>3, d=>3, f=>5
* a=>2, b=>1, c=>3, d=>3, f=>4
* a=>2, b=>1, c=>3, d=>3, f=>5
* a=>2, b=>2, c=>3, d=>3, f=>4
* a=>2, b=>2, c=>3, d=>3, f=>5
* @param relations a map from sets of E to sets of F. * @return a set of maps from E to F. */ public Set> allMaps(Map,Set> relations){ Set>> maps = new HashSet>>(); for(Set e : relations.keySet()) maps.add(this.allMaps(e,relations.get(e))); Collection>> permutations = new SetTools>().permutations(maps); Set> result = new HashSet>(); for(Set> mapSet: permutations){ result.add(this.combine(mapSet)); } return result; } /** * Computes the complete set of maps from E to F such that the following * condition holds. For every map "m" in the result the set m.keySet() * is equal to relations.keySet() and each * element "e" in m.keySet() is mapped to an element "f" such that "f" in * relations.get(S) with "e" in S. For example the map:
* a => {1,2}
* b => {3}
* c => {4,5}
* yields the set of maps:
* a=>1, b=>3, c=>4
* a=>1, b=>3, c=>5
* a=>2, b=>3, c=>4
* a=>2, b=>3, c=>5
* @param relations a map from sets of E to sets of F. * @return a set of maps from E to F. */ public Set> allMapsSingleSource(Map> relations){ Set> result = new HashSet>(); result.add(new HashMap()); for(E key: relations.keySet()){ Set> newResult = new HashSet>(); for(Map map: result){ for(F val: relations.get(key)){ Map newMap = new HashMap(map); newMap.put(key, val); newResult.add(newMap); } } result = newResult; } return result; } /** Computes all bijections from E to F. * E and F have to be of the same cardinality. * @param domain some set. * @param range some set. * @return all bijections from E to F. */ public Set> allBijections(Collection domain, Collection range){ if(domain.size() != range.size()) throw new IllegalArgumentException("Domain and range have to be of the same cardinality"); Set> result = new HashSet>(); if(domain.size() == 1){ Map newMap = new HashMap(); newMap.put(domain.iterator().next(), range.iterator().next()); result.add(newMap); return result; } E elem = domain.iterator().next(); Set newDomain = new HashSet(domain); newDomain.remove(elem); for(F elem2: range){ Set newRange = new HashSet(range); newRange.remove(elem2); Set> subResult = this.allBijections(newDomain, newRange); for(Map map: subResult){ map.put(elem, elem2); result.add(map); } } return result; } /** * This methods computes all maps from domain to range. * @param domain a set of elements. * @param range a set of elements * @return a set of maps, where every map maps any element of domain to an * element of range. */ public Set> allMaps(Set domain, Set range){ Set> allMaps = new HashSet>(); Stack,Stack>> stack = new Stack,Stack>>(); Pair,Stack> elem = new Pair,Stack>(); elem.setFirst(new HashMap()); elem.setSecond(new Stack()); elem.getSecond().addAll(domain); stack.push(elem); while(!stack.isEmpty()){ elem = stack.pop(); if(elem.getSecond().isEmpty()){ allMaps.add(elem.getFirst()); }else{ E domelem = elem.getSecond().pop(); for(F image: range){ Map newMap = new HashMap(elem.getFirst()); newMap.put(domelem, image); Stack newStack = new Stack(); newStack.addAll(elem.getSecond()); stack.push(new Pair,Stack>(newMap,newStack)); } } } return allMaps; } /** * Combines all maps in singleMaps to one maps containing * every assignment of each map in singleMaps. * @param singleMaps the set of maps to be combined. * @return a single map. * @throws IllegalArgumentException if one key is used * in more than one map of singleMaps. */ public Map combine(Set> singleMaps)throws IllegalArgumentException{ Map result = new HashMap(); for(Map map: singleMaps){ for(E key: map.keySet()){ if(result.containsKey(key)) throw new IllegalArgumentException("Value of key " + key + " is ambiguous."); result.put(key, map.get(key)); } } return result; } /** * Checks whether the given map is injective, i.e. whether no two different keys * are assigned the same value. * @param map a map * @return "true" iff the given map is injective. */ public static boolean isInjective(Map map){ for(Object key1: map.keySet()) for(Object key2: map.keySet()) if(key1 != key2) if(map.get(key1).equals(map.get(key2))) return false; return true; } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy