001    package net.sf.cpsolver.exam.neighbours;
002    
003    import java.text.DecimalFormat;
004    
005    import org.apache.log4j.Logger;
006    
007    import net.sf.cpsolver.exam.model.Exam;
008    import net.sf.cpsolver.exam.model.ExamModel;
009    import net.sf.cpsolver.exam.model.ExamPlacement;
010    import net.sf.cpsolver.ifs.model.SimpleNeighbour;
011    
012    /**
013     * Extension of {@link SimpleNeighbour}. The only difference is that the value (
014     * {@link SimpleNeighbour#value()}) is decreased by 1000 if the selected
015     * variable has no current assignment. <br>
016     * <br>
017     * 
018     * @version ExamTT 1.2 (Examination Timetabling)<br>
019     *          Copyright (C) 2008 - 2010 Tomas Muller<br>
020     *          <a href="mailto:muller@unitime.org">muller@unitime.org</a><br>
021     *          <a href="http://muller.unitime.org">http://muller.unitime.org</a><br>
022     * <br>
023     *          This library is free software; you can redistribute it and/or modify
024     *          it under the terms of the GNU Lesser General Public License as
025     *          published by the Free Software Foundation; either version 3 of the
026     *          License, or (at your option) any later version. <br>
027     * <br>
028     *          This library is distributed in the hope that it will be useful, but
029     *          WITHOUT ANY WARRANTY; without even the implied warranty of
030     *          MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
031     *          Lesser General Public License for more details. <br>
032     * <br>
033     *          You should have received a copy of the GNU Lesser General Public
034     *          License along with this library; if not see
035     *          <a href='http://www.gnu.org/licenses/'>http://www.gnu.org/licenses/</a>.
036     */
037    public class ExamSimpleNeighbour extends SimpleNeighbour<Exam, ExamPlacement> {
038        private static Logger sLog = Logger.getLogger(ExamSimpleNeighbour.class);
039        private static boolean sCheck = false;
040        private double iValue = 0;
041        private double iDx;
042    
043        public ExamSimpleNeighbour(ExamPlacement placement) {
044            super(placement.variable(), placement);
045            iValue = placement.toDouble();
046            if (placement.variable().getAssignment() != null)
047                iValue -= placement.variable().getAssignment().toDouble();
048            else
049                iValue -= 1000;
050            if (sCheck) {
051                iDx = placement.toDouble();
052                if (placement.variable().getAssignment() != null)
053                    iDx -= placement.variable().getAssignment().toDouble();
054            }
055        }
056    
057        @Override
058        public void assign(long iteration) {
059            if (sCheck) {
060                double beforeVal = getVariable().getModel().getTotalValue();
061                double[] beforeValM = ((ExamModel) getVariable().getModel()).getTotalMultiValue();
062                String n = toString();
063                getVariable().assign(iteration, getValue());
064                double afterVal = getVariable().getModel().getTotalValue();
065                double[] afterValM = ((ExamModel) getVariable().getModel()).getTotalMultiValue();
066                /*
067                 * int before = getVariable().getModel().nrUnassignedVariables();
068                 * int after = getVariable().getModel().nrUnassignedVariables(); if
069                 * (after>before) {
070                 * sLog.error("-- assignment mischmatch (delta:"+(after
071                 * -before)+")"); sLog.error("  -- neighbour: "+n); }
072                 */
073                if (Math.abs(afterVal - beforeVal - iDx) >= 0.0000001) {
074                    sLog.error("-- value mischmatch (delta:" + (afterVal - beforeVal) + ", value:" + iDx + ")");
075                    sLog.error("  -- neighbour: " + n);
076                    sLog.error("  -- solution:  " + toString(afterValM, beforeValM));
077                }
078            } else {
079                getVariable().assign(iteration, getValue());
080            }
081        }
082    
083        protected static String toString(double[] x) {
084            DecimalFormat df = new DecimalFormat("0.00");
085            StringBuffer s = new StringBuffer();
086            for (int i = 0; i < x.length; i++) {
087                if (i > 0)
088                    s.append(",");
089                s.append(df.format(x[i]));
090            }
091            return "[" + s.toString() + "]";
092        }
093    
094        protected static String toString(double[] x, double[] y) {
095            DecimalFormat df = new DecimalFormat("0.00");
096            StringBuffer s = new StringBuffer();
097            for (int i = 0; i < x.length; i++) {
098                if (i > 0)
099                    s.append(",");
100                s.append(df.format(x[i] - y[i]));
101            }
102            return "[" + s.toString() + "]";
103        }
104    
105        @Override
106        public String toString() {
107            return getVariable().getAssignment() + " -> " + getValue().toString() + " / " + " (value:" + value() + ")";
108        }
109    
110        @Override
111        public double value() {
112            return iValue;
113        }
114    }