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

fr.lirmm.graphik.util.Partition Maven / Gradle / Ivy

There is a newer version: 1.6.1
Show newest version
/*
 * Copyright (C) Inria Sophia Antipolis - Méditerranée / LIRMM
 * (Université de Montpellier & CNRS) (2014 - 2017)
 *
 * Contributors :
 *
 * Clément SIPIETER 
 * Mélanie KÖNIG
 * Swan ROCHER
 * Jean-François BAGET
 * Michel LECLÈRE
 * Marie-Laure MUGNIER 
 *
 *
 * This file is part of Graal .
 *
 * This software is governed by the CeCILL  license under French law and
 * abiding by the rules of distribution of free software.  You can  use,
 * modify and/ or redistribute the software under the terms of the CeCILL
 * license as circulated by CEA, CNRS and INRIA at the following URL
 * "http://www.cecill.info".
 *
 * As a counterpart to the access to the source code and  rights to copy,
 * modify and redistribute granted by the license, users are provided only
 * with a limited warranty  and the software's author,  the holder of the
 * economic rights,  and the successive licensors  have only  limited
 * liability.
 *
 * In this respect, the user's attention is drawn to the risks associated
 * with loading,  using,  modifying and/or developing or reproducing the
 * software by the user in light of its specific status of free software,
 * that may mean  that it is complicated to manipulate,  and  that  also
 * therefore means  that it is reserved for developers  and  experienced
 * professionals having in-depth computer knowledge. Users are therefore
 * encouraged to load and test the software's suitability as regards their
 * requirements in conditions enabling the security of their systems and/or
 * data to be ensured and,  more generally, to use and operate it in the
 * same conditions as regards security.
 *
 * The fact that you are presently reading this means that you have had
 * knowledge of the CeCILL license and that you accept its terms.
 */
 package fr.lirmm.graphik.util;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;

/**
 * A partition of terms. A partition can be associated with a substition : two
 * terms are in the same class if one is the image of the other ex: the
 * partition associated with {(a,b)(c,b)(d,e)(e,f)} is {{a,b,c}{d,e,f}}
 */

public class Partition implements Iterable> {

	protected List> partition;

	// //////////////////////////////////////////////////////////////////////////
	// CONSTRUCTORS
	// //////////////////////////////////////////////////////////////////////////

	public Partition() {
		this.partition = new ArrayList>();
	}

	/**
	 * Copy constructor
	 * 
	 * @param partition
	 */
	public Partition(Partition partition) {
		this();
		for (Collection classs : partition) {
			this.partition.add(new ArrayList(classs));
		}
	}

	/**
	 * Create a partition based on the position of elements in the two lists.
	 * 
	 * @param list1
	 * @param list2
	 */
	public Partition(List list1, List list2) {
		this();
		Iterator it1 = list1.iterator();
		Iterator it2 = list2.iterator();

		while (it1.hasNext()) {
			E e1 = it1.next();
			if (it2.hasNext()) {
				this.add(e1, it2.next());
			}
		}
	}

	// //////////////////////////////////////////////////////////////////////////
	// METHODS
	// //////////////////////////////////////////////////////////////////////////

	public E getRepresentant(E e) {
		for (List classs : this) {
			if (classs.contains(e)) {
				return classs.get(0);
			}
		}
		return e;
	}

	public ArrayList getClass(E e) {
		for (ArrayList classs : this) {
			if (classs.contains(e)) {
				return classs;
			}
		}
		return null;
	}

	/**
	 * Add the couple to the partition
	 */
	public void add(E t, E im) {
		if (!t.equals(im)) {
			ArrayList tset = null;
			ArrayList imset = null;
			// we look for the equivalence set of t and im if exists
			Iterator> ip = partition.iterator();
			while ((tset == null || imset == null) && ip.hasNext()) {
				ArrayList s = ip.next();
				Iterator is = s.iterator();
				while ((tset == null || imset == null) && is.hasNext()) {
					E e = is.next();
					if (e.equals(t))
						tset = s;
					if (e.equals(im))
						imset = s;
				}
			}
			// im and t have not equivalence set so we create a new one for its
			if (tset == null && imset == null) {
				ArrayList s = new ArrayList();
				s.add(t);
				s.add(im);
				partition.add(s);
			}
			// im has not an equivalence set but t has one so we add im in t's
			// equivalence set
			else if (imset == null) {
				tset.add(im);
			}
			// t has not an equivalence set but im has one so we add t in im's
			// equivalence set
			else if (tset == null) {
				imset.add(t);
			}
			// t and im have different equivalence sets so we append the two
			// equivalence set
			else if (tset != imset) {
				tset.addAll(imset);
				partition.remove(imset);
			}
		}
	}

	/**
	 * @param toAdd
	 *            (const)
	 */
	public void addClass(ArrayList toAdd) {
		Iterator> i = partition.iterator();
		ArrayList fusion = null;
		while (i.hasNext()) {
			ArrayList cl = i.next();
			Iterator it = cl.iterator();
			boolean contain = false;
			while (!contain && it.hasNext()) {
				E t = it.next();
				if (toAdd.contains(t)) {
					contain = true;
					if (fusion == null) {
						fusion = cl;
						cl.addAll(toAdd);
					} else {
						fusion.addAll(cl);
						i.remove();
					}
				}
			}
		}
		if (fusion == null)
			partition.add(new ArrayList(toAdd));
	}

	/**
	 * Return the join of this and the given partition p the join of two
	 * partition is obtained by making the union of their non-disjoint classes
	 * until stability ex: the join of {{a,b,c},{d,e}} and {{e,g},{k,l}} is
	 * {{a,b,c},{d,e,g},{k,l}}
	 */
	public Partition join(Partition p) {
		Partition res = new Partition();
		for (ArrayList cl : partition) {
			res.partition.add(new ArrayList(cl));
		}
		for (ArrayList cl : p.partition)
			res.addClass(cl);
		return res;
	}

	@Override
	public Iterator> iterator() {
		return partition.iterator();
	}

	// //////////////////////////////////////////////////////////////////////////
	// OBJECT METHODS
	// //////////////////////////////////////////////////////////////////////////

	@Override
	public String toString() {
		return partition.toString();
	}
	
	@Override
	public int hashCode() {
		int hashCode = 0;
		for (ArrayList list : this) {
			for (E e : list) {
				hashCode = 31 * hashCode + e.hashCode();
			}
		}
		return hashCode * 31 + this.partition.size();
	}

	@Override
	public boolean equals(Object obj) {
		if (this == obj) {
			return true;
		}
		if (obj == null || !(obj instanceof Partition)) {
			return false;
		}

		@SuppressWarnings("unchecked")
		Partition other = (Partition) obj;
		@SuppressWarnings("unchecked")
		Partition me = (Partition) this;

		for (ArrayList list : me) {
			for(Object e1 : list) {
				for(Object e2 : list) {
					ArrayList l1 = other.getClass(e1);
					ArrayList l2 = other.getClass(e2);
					if (l1 != l2 || l1 == null) {
						return false;
					}
				}
			}
		}
		for (ArrayList list : other) {
			for (Object e1 : list) {
				for (Object e2 : list) {
					ArrayList l1 = me.getClass(e1);
					ArrayList l2 = me.getClass(e2);
					if (l1 != l2 || l1 == null) {
						return false;
					}
				}
			}
		}
		return true;
	}

}