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