/* * UserLib.java * ------------- * $Id: UserLib.java,v 1.19 2000/11/28 00:48:09 chenli Exp $ */ import java.util.*; class UserLib { public static void myerror(String str) { System.out.println(str); System.exit(1); } public static void myprintln(String str) { if ( GoodPlan.debug == true ) System.out.println(str); } public static String getChar(int index, boolean isConstant) { if (isConstant) return "" + index; return "X" + index; /* if (GoodPlan.isView) return "X" + index; else return "X" + index; */ } /** * Gets the i^th character. */ public static String getChar(int index) { return getChar(index, false); } /** * generates all possible mappings from one set of args to another set * of args. Here is the design. Suppose we have A, B, C, D as the * distinguished variables. For A, it can be mapped to A, B, C, or D. * For each of them, we expand it (recursively) by consider the four * possible mapping targets of B, and so on. */ public static Vector genAllMappings(Vector srcArgs, Vector dstArgs) { Map partialMap = new HashMap(); Vector mappings = new Vector(); buildHeadHomos(mappings, srcArgs, dstArgs, partialMap, 0); return mappings; } /** * recursively build mappings */ private static void buildHeadHomos(Vector headHomos, Vector srcArgs, Vector dstArgs, Map partialMap, int srcArgIndex) { if (srcArgIndex == srcArgs.size()) { // we reach the last arg // we need to clone one so that we can operate on the partial one later Map completeMap = (Map) ((HashMap) partialMap).clone(); headHomos.add(new Mapping(completeMap)); return; } for (int dstArgIndex = 0; dstArgIndex < dstArgs.size(); dstArgIndex ++) { // adds "src arg -> dst arg" to the partial mapping partialMap.put(srcArgs.elementAt(srcArgIndex), dstArgs.elementAt(dstArgIndex)); // recursively builds a mapping buildHeadHomos(headHomos, srcArgs, dstArgs, partialMap, srcArgIndex + 1); // removes "src arg -> dst arg" from the partial mapping partialMap.remove(srcArgs.elementAt(srcArgIndex)); } } /** * given args, finds all their partitions. For each partition, equates * the args in each group to any arg in the group. */ public static Vector genPartitionEquMappings(Vector args) { HashSet partitions = (HashSet) genPartitions(args); Vector mappings = new Vector(); for (Iterator iter = partitions.iterator(); iter.hasNext();) { HashSet onePartition = (HashSet) iter.next(); // one partition // scan the groups in this partition Map map = new HashMap(); for (Iterator iterGroup = onePartition.iterator(); iterGroup.hasNext();) { HashSet group = (HashSet) iterGroup.next(); // one group if (group.size() <= 0 ) myerror("genPartitionEquMappings() " + "Wrong partitions. A group should have " + "an argument."); boolean firstOne = true; Argument dstArg = null; // scan the arg in a group for (Iterator iterArg = group.iterator(); iterArg.hasNext();) { Argument srcArg = (Argument) iterArg.next(); // one argument if (firstOne) { // picks the first argument as the dst argument dstArg = srcArg; firstOne = false; } // map them map.put(srcArg, dstArg); } } mappings.add(new Mapping(map)); } return mappings; } /** * Generates all partitions of a set, represented as a vector */ public static Set genPartitions(Vector v) { Set partitions = new HashSet(); // all partitions buildPartitions(partitions, v, 0); return partitions; } /** * recursively build partitions */ private static void buildPartitions(Set partitions, Vector v, int index) { if (index == v.size() - 1) { // creates one partition with one group with 1 element Set newPartition = new HashSet(); HashSet group = new HashSet(); group.add(v.elementAt(index)); newPartition.add(group); partitions.add(newPartition); return; } // recursively builds subsets buildPartitions(partitions, v, index + 1); // expanding the partitions // iterator doesn't allow us to add new partitions, so let's use another // set to keep the new partitions HashSet newPartitions = new HashSet(); for (Iterator iter = partitions.iterator(); iter.hasNext();) { HashSet onePartition = (HashSet) iter.next(); // one partition // 1) for each partition, for each group, add the current element to // form a new partition; for (Iterator iterGroup = onePartition.iterator(); iterGroup.hasNext();) { HashSet currentGroup = (HashSet) iterGroup.next(); // adds the currents element to this group HashSet newGroup = (HashSet) currentGroup.clone(); newGroup.add(v.elementAt(index)); // creates a new partition and adds this group HashSet newPartition = new HashSet(); newPartition.add(newGroup); // copies all other groups in this partition for (Iterator iterOtherGroup = onePartition.iterator(); iterOtherGroup.hasNext();) { HashSet otherGroup = (HashSet) iterOtherGroup.next(); if (otherGroup != currentGroup) newPartition.add(otherGroup.clone()); } // adds this partition to the new set newPartitions.add(newPartition); } // 2) for each partition, expands it by adding a group with the // current element. HashSet newPartition = new HashSet(); HashSet group = new HashSet(); group.add(v.elementAt(index)); newPartition.add(group); for (Iterator iterGroup = onePartition.iterator(); iterGroup.hasNext();) { group = (HashSet) iterGroup.next(); newPartition.add(group.clone()); } newPartitions.add(newPartition); // remove the old partition iter.remove(); } partitions.addAll(newPartitions); } /** * Generates all subsets of a set, represented as a hashset. */ public static HashSet genSubsets(HashSet h) { // translates it to a vector Vector v = new Vector(); for (Iterator iter = h.iterator(); iter.hasNext();) { v.add(iter.next()); } return genSubsets(v); } /** * Generates all subsets of a set, represented as a vector */ public static HashSet genSubsets(Vector v) { //UserLib.myprintln("In genSubsets(): v = " + v); HashSet subsets = new HashSet(); // all subsets buildSubsets(subsets, v, 0); return subsets; } /** * recursively build subsets */ private static void buildSubsets(HashSet subsets, Vector v, int index) { /*UserLib.myprintln("subsets.size() = " + subsets.size() + "index = " + index);*/ if (index == v.size()) {// we reach the last element subsets.add(new HashSet()); // creates an empty subset return; } // recursively builds subsets buildSubsets(subsets, v, index + 1); // expanding the subsets by adding the current element to each subset // while keeping the old ones // iterator doesn't allow us to add new subsets, so let's use another // set to keep the new subsets //UserLib.myprintln("before: subsets() = " + subsets); //UserLib.myprintln("before: subsets.size() = " + subsets.size()); HashSet newSubsets = new HashSet(); for (Iterator iter = subsets.iterator(); iter.hasNext();) { HashSet subset = (HashSet) iter.next(); HashSet newSubset = (HashSet) subset.clone(); newSubset.add(v.elementAt(index)); // add the current element newSubsets.add(newSubset); } subsets.addAll(newSubsets); //UserLib.myprintln("after: subsets.size() = " + subsets.size()); //UserLib.myprintln("after: subsets() = " + subsets); } /** * Generates all sequences of length "length" for a set of objects * in which each object should appear at least once. */ public static Vector getAllSeqs(Vector v, int length) { HashSet hs = new HashSet(v); return getAllSeqs(hs, length); } /** * Generates all sequences of length "length" for a set of objects * in which each object should appear at least once. */ public static Vector getAllSeqs(HashSet objectSet, int length) { Vector allSeqs = new Vector(); Vector oneSeq = new Vector(); if (length == 0) allSeqs.add(oneSeq); else buildAllSeq(objectSet, length, oneSeq, allSeqs); return allSeqs; } /** * Recursively builds the sequences. */ private static void buildAllSeq(HashSet objectSet, int length, Vector oneSeq, Vector allSeqs) { // if there are more objects than the length, do nothing if (objectSet.size() > length) return; if (objectSet.size() == length) { // generates all the permutations of the objects and returns HashSet permutations = UserLib.genPermutations(objectSet); for (Iterator iter = permutations.iterator(); iter.hasNext();) { Vector permutation = (Vector) iter.next(); Vector newSeq = (Vector) oneSeq.clone(); newSeq.addAll(permutation); // concates the two sequences allSeqs.add(newSeq); // generates one complete sequence } return; } // iteratively adds an object to the vector for (Iterator iter = objectSet.iterator(); iter.hasNext();) { Object obj = iter.next(); HashSet newObjectSet = (HashSet) objectSet.clone(); // if the object doesn't appear in the existing sequence if (!oneSeq.contains(obj)) { newObjectSet.remove(obj); } Vector newSeq = (Vector) oneSeq.clone(); newSeq.add(obj); // adds this object to the vector // recursively calls the function buildAllSeq(newObjectSet, length - 1, newSeq, allSeqs); } } /** * Creates a set of all permutations (represented as vectors) for a * given vector of objects. */ public static HashSet genPermutations(Vector v) { HashSet hs = new HashSet(v); return genPermutations(hs); } /** * Creates a set of all permutations (represented as vectors) for a * given set of objects. */ public static HashSet genPermutations(HashSet objectSet) { HashSet allPermutations = new HashSet(); Vector onePermutation = new Vector(); buildPermutations(objectSet, onePermutation, allPermutations); return allPermutations; } private static void buildPermutations(HashSet objectSet, Vector onePermutation, HashSet allPermutations) { if (objectSet.isEmpty()) { allPermutations.add(onePermutation); return; } // iteratively adds an object to the permutation for (Iterator iter = objectSet.iterator(); iter.hasNext();) { Object obj = iter.next(); // adds this object to the vector Vector newPermutation = (Vector) onePermutation.clone(); newPermutation.add(obj); HashSet newObjectSet = (HashSet) objectSet.clone(); newObjectSet.remove(obj); // recursively calls the function buildPermutations(newObjectSet, newPermutation, allPermutations); } } /** * Creates all the subsets with size k of a given hashset */ public static HashSet genSubsets(HashSet objectSet, int k) { if (objectSet.size() < k ) return (new HashSet()); // empty return buildSubsets(objectSet, k); } /** * recursive helper. */ static HashSet buildSubsets(HashSet objectSet, int k) { HashSet result = new HashSet(); if (k == 0) { result.add(new HashSet()); // empty set return result; } if (objectSet.size() == k ) { result.add(objectSet.clone()); return result; } if (objectSet.size() == 0) UserLib.myerror("UserLib.buildSubsets(): error()!"); // randomly pick an object Object obj = objectSet.iterator().next(); // removed the current object HashSet tmpObjSet = (HashSet) objectSet.clone(); tmpObjSet.remove(obj); // part 1: buildSubsets(objectSet - o, k); // without o HashSet result1 = buildSubsets(tmpObjSet, k); result.addAll(result1); // part 2: buildSubsets(objectSet - o, k - 1); // with o HashSet result2 = buildSubsets(tmpObjSet, k - 1); // add the current object to each subset in result 2 for (Iterator iter = result2.iterator(); iter.hasNext();) { HashSet oneSet = (HashSet) iter.next(); // one partition oneSet.add(obj); result.add(oneSet); } return result; } /** * Checks if two sets are disjoint */ public static boolean disjoint(HashSet set1, HashSet set2) { HashSet tmpSet = (HashSet) set1.clone(); tmpSet.retainAll(set2); return (tmpSet.isEmpty()); } /** * Unit test. */ public static void main(String[] args) { Vector v = new Vector(); v.add(new Integer(1)); v.add(new Integer(2)); v.add(new Integer(3)); v.add(new Integer(4)); System.out.println("vector = " + v); // tests genSubsets HashSet subsets = (HashSet) genSubsets(v); System.out.println("Subsets are:" + subsets); // tests genPartitions HashSet partitions = (HashSet) genPartitions(v); System.out.println("partitions are:" + partitions); // tests vector.clone() Vector newV = (Vector) v.clone(); System.out.println("New vector = " + newV); newV.remove(0); System.out.println("After the deletion, New vector = " + newV); System.out.println("After the deletion, old vector = " + v); } }