001package org.cpsolver.ifs.extension; 002 003import java.util.Comparator; 004 005import org.cpsolver.ifs.model.Constraint; 006import org.cpsolver.ifs.model.Value; 007 008 009/** 010 * This class describing an assignment of a value to a variable together with a 011 * counter (used by CBS). 012 * 013 * Counter also supports aging: the counter is multiplied by aging factor for 014 * each iteration. 015 * 016 * @version IFS 1.3 (Iterative Forward Search)<br> 017 * Copyright (C) 2006 - 2014 Tomáš Müller<br> 018 * <a href="mailto:muller@unitime.org">muller@unitime.org</a><br> 019 * <a href="http://muller.unitime.org">http://muller.unitime.org</a><br> 020 * <br> 021 * This library is free software; you can redistribute it and/or modify 022 * it under the terms of the GNU Lesser General Public License as 023 * published by the Free Software Foundation; either version 3 of the 024 * License, or (at your option) any later version. <br> 025 * <br> 026 * This library is distributed in the hope that it will be useful, but 027 * WITHOUT ANY WARRANTY; without even the implied warranty of 028 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 029 * Lesser General Public License for more details. <br> 030 * <br> 031 * You should have received a copy of the GNU Lesser General Public 032 * License along with this library; if not see 033 * <a href='http://www.gnu.org/licenses/'>http://www.gnu.org/licenses/</a>. 034 * @param <T> Value 035 */ 036public class AssignedValue<T extends Value<?, T>> { 037 private T iValue; 038 private double iCounter = 1.0; 039 private long iLastRevision; 040 private double iAging = 1.0; 041 private Constraint<?, T> iConstraint = null; 042 043 /** 044 * Constructor 045 * 046 * @param iteration 047 * current iteration 048 * @param value 049 * value 050 * @param aging 051 * aging factor 052 */ 053 public AssignedValue(long iteration, T value, double aging) { 054 iValue = value; 055 iLastRevision = iteration; 056 iAging = aging; 057 } 058 059 /** Returns value 060 * @return value */ 061 public T getValue() { 062 return iValue; 063 } 064 065 /** 066 * Increments counter 067 * 068 * @param iteration 069 * current iteration 070 */ 071 public void incCounter(long iteration) { 072 revise(iteration); 073 iCounter += 1.0; 074 } 075 076 /** 077 * Set counter 078 * 079 * @param cnt 080 * new value 081 */ 082 public void setCounter(double cnt) { 083 iCounter = cnt; 084 } 085 086 /** 087 * Get counter 088 * 089 * @param iteration 090 * current iteration 091 * @return counter 092 */ 093 public double getCounter(long iteration) { 094 if (iteration == 0l) 095 return iCounter; 096 if (iAging == 1.0) 097 return iCounter; 098 return iCounter * Math.pow(iAging, iteration - iLastRevision); 099 } 100 101 /** Returns constraint 102 * @return constraint 103 **/ 104 public Constraint<?, T> getConstraint() { 105 return iConstraint; 106 } 107 108 /** Sets constraint 109 * @param constraint a constraint 110 **/ 111 public void setConstraint(Constraint<?, T> constraint) { 112 iConstraint = constraint; 113 } 114 115 /** 116 * Revise counter. If aging is used, counter is adopted to the current 117 * iteration: it is multiplied by aging factor powered by the number of 118 * iterations since last revision. 119 * @param iteration current iteration 120 */ 121 public synchronized void revise(long iteration) { 122 if (iAging == 1.0) 123 return; 124 iCounter *= Math.pow(iAging, iteration - iLastRevision); 125 iLastRevision = iteration; 126 } 127 128 /** 129 * Combine two integers (for hash code) 130 * @param a first integer 131 * @param b second integer 132 * @return combined hash code 133 */ 134 public static int combine(int a, int b) { 135 int ret = 0; 136 for (int i = 0; i < 15; i++) 137 ret = ret | ((a & (1 << i)) << i) | ((b & (1 << i)) << (i + 1)); 138 return ret; 139 } 140 141 @Override 142 public int hashCode() { 143 return iValue.hashCode(); 144 } 145 146 @Override 147 public boolean equals(Object o) { 148 if (o == null || !(o instanceof AssignedValue<?>)) 149 return false; 150 return ((AssignedValue<?>) o).getValue().equals(getValue()); 151 } 152 153 /** String representation */ 154 @Override 155 public String toString() { 156 return toString(0l, true); 157 } 158 159 /** String representation (e.g., 10x A := a) 160 * @param iteration current iteration 161 * @param assignment true if assignment 162 * @return string representation of the assignment 163 **/ 164 public String toString(long iteration, boolean assignment) { 165 return (assignment ? getCounter(iteration) + "x " : "") + getValue().variable().getName() 166 + (assignment ? " := " : " != ") + getValue().getName() + (getConstraint() != null ? " (" + getConstraint() + ")" : ""); 167 } 168 169 /** Compare two assignments (their counters) 170 * @param iteration current iteration 171 * @param a another assignment 172 * @return comparison 173 **/ 174 public int compareTo(long iteration, AssignedValue<T> a) { 175 int cmp = getValue().variable().getName().compareTo(a.getValue().variable().getName()); 176 if (cmp != 0) 177 return cmp; 178 if (getCounter(iteration) != a.getCounter(iteration)) 179 return (getCounter(iteration) < a.getCounter(iteration) ? 1 : -1); 180 return getValue().getName().compareTo(a.getValue().getName()); 181 } 182 183 /** Assignment comparator 184 * @param <E> a value 185 **/ 186 public static class AssignmentComparator<E extends Value<?, E>> implements Comparator<AssignedValue<E>> { 187 private long iIteration; 188 189 public AssignmentComparator(long iteration) { 190 iIteration = iteration; 191 } 192 193 @Override 194 public int compare(AssignedValue<E> a1, AssignedValue<E> a2) { 195 return a1.compareTo(iIteration, a2); 196 } 197 } 198}