/* * RapidMiner * * Copyright (C) 2001-2008 by Rapid-I and the contributors * * Complete list of developers available at our web site: * * http://rapid-i.com * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * 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 Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see http://www.gnu.org/licenses/. */ package com.rapidminer.operator.learner.clustering.constrained.constraints; import com.rapidminer.operator.learner.clustering.Cluster; import com.rapidminer.operator.learner.clustering.ClusterModel; import com.rapidminer.operator.learner.clustering.FlatClusterModel; /** * Models Must-Link- or Cannot-Link-constraints * * @author Alexander Daxenberger * @version $Id: LinkClusterConstraint.java,v 1.8 2008/09/12 10:31:46 tobiasmalbrecht Exp $ */ public class LinkClusterConstraint implements ClusterConstraint { public static final byte MUST_LINK = 0; public static final byte CANNOT_LINK = 1; private String id0; private String id1; private double weight; private byte type; private int hashCode; public LinkClusterConstraint(String id0, String id1, double weight, byte type) { try { if (Double.parseDouble(id0) > Double.parseDouble(id1)) { this.id0 = id1; this.id1 = id0; } else { this.id0 = id0; this.id1 = id1; } } catch (Exception e) { this.id0 = id0; this.id1 = id1; } this.weight = weight; this.type = type; this.hashCode = this.toString().hashCode(); } public String getId0() { return this.id0; } public String getId1() { return this.id1; } public String getOtherId(String id) { if (this.id0.equals(id)) return this.id1; else if (this.id1.equals(id)) return this.id0; else return null; } public byte getType() { return this.type; } public boolean constraintViolated(ClusterModel clusterModel) { FlatClusterModel cm; Cluster c; Cluster c0 = null; Cluster c1 = null; if (clusterModel instanceof FlatClusterModel) { cm = (FlatClusterModel)clusterModel; for (int i=0; i < cm.getNumberOfClusters(); i++) { c = cm.getClusterAt(i); if ((c0 == null) && (c.contains(this.id0))) c0 = c; if ((c1 == null) && (c.contains(this.id1))) c1 = c; } if (this.type == MUST_LINK) return (c0 != c1); else return (c0 == c1); } return false; } public boolean constraintViolated(Cluster cluster) { if (this.type == MUST_LINK) return (cluster.contains(this.id0) != cluster.contains(this.id1)); else return (cluster.contains(this.id0) && cluster.contains(this.id1)); } /** * Returns true, if this constraint will be violated if the given object id * is added to the cluster. * * @param id * @param cluster */ public boolean constraintViolatedIfAdded(String id, Cluster cluster) { if (this.type == MUST_LINK) return ((cluster.contains(this.id0) || (this.id0.equals(id))) != (cluster.contains(this.id1) || (this.id1.equals(id)))); else return ((cluster.contains(this.id0) || (this.id0.equals(id))) && (cluster.contains(this.id1) || (this.id1.equals(id)))); } public double getConstraintWeight(ClusterModel clusterModel) { return this.weight; } public boolean equals(Object o) { LinkClusterConstraint lct; if (o instanceof LinkClusterConstraint) { lct = (LinkClusterConstraint)o; if (this.type == lct.getType()) { if ((this.id0.equals(lct.getId0()) && this.id1.equals(lct.getId1())) || (this.id0.equals(lct.getId1()) && this.id1.equals(lct.getId0()))) return true; } } return false; } public int hashCode() { return this.hashCode; } public String toString() { StringBuffer sb = new StringBuffer(); sb.append(this.id0); if (this.type == MUST_LINK) sb.append("---"); else sb.append("-X-"); sb.append(this.id1); return sb.toString(); } public LinkClusterConstraint clone() { return new LinkClusterConstraint(this.id0, this.id1, this.weight, this.type); } }