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.ExamModel;
008    import net.sf.cpsolver.exam.model.ExamPlacement;
009    import net.sf.cpsolver.ifs.model.SimpleNeighbour;
010    /**
011     * Extension of {@link SimpleNeighbour}. The only difference is that
012     * the value ({@link SimpleNeighbour#value()}) is decreased by 1000 if the
013     * selected variable has no current assignment.
014     * <br><br>
015     * 
016     * @version
017     * ExamTT 1.1 (Examination Timetabling)<br>
018     * Copyright (C) 2008 Tomáš Müller<br>
019     * <a href="mailto:muller@unitime.org">muller@unitime.org</a><br>
020     * Lazenska 391, 76314 Zlin, Czech Republic<br>
021     * <br>
022     * This library is free software; you can redistribute it and/or
023     * modify it under the terms of the GNU Lesser General Public
024     * License as published by the Free Software Foundation; either
025     * version 2.1 of the License, or (at your option) any later version.
026     * <br><br>
027     * This library is distributed in the hope that it will be useful,
028     * but 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.
031     * <br><br>
032     * You should have received a copy of the GNU Lesser General Public
033     * License along with this library; if not, write to the Free Software
034     * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
035     */
036    public class ExamSimpleNeighbour extends SimpleNeighbour {
037        private static Logger sLog = Logger.getLogger(ExamSimpleNeighbour.class);
038        private static boolean sCheck = false;
039        private double iValue = 0;
040        private double iDx;
041        
042        public ExamSimpleNeighbour(ExamPlacement placement) {
043            super(placement.variable(),placement);
044            iValue = placement.toDouble();
045            if (placement.variable().getAssignment()!=null)
046                iValue -= placement.variable().getAssignment().toDouble();
047            else
048                iValue -= 1000;
049            if (sCheck) {
050                iDx = placement.toDouble(); 
051                if (placement.variable().getAssignment()!=null)
052                    iDx -= placement.variable().getAssignment().toDouble();
053            }
054        }
055        
056        public void assign(long iteration) {
057            if (sCheck) {
058                int before = getVariable().getModel().nrUnassignedVariables();
059                double beforeVal = getVariable().getModel().getTotalValue();
060                double[] beforeValM = ((ExamModel)getVariable().getModel()).getTotalMultiValue();
061                String n = toString();
062                getVariable().assign(iteration, getValue());
063                int after = getVariable().getModel().nrUnassignedVariables();
064                double afterVal = getVariable().getModel().getTotalValue();
065                double[] afterValM = ((ExamModel)getVariable().getModel()).getTotalMultiValue();
066                /*if (after>before) {
067                    sLog.error("-- assignment mischmatch (delta:"+(after-before)+")");
068                    sLog.error("  -- neighbour: "+n);
069                }*/
070                if (Math.abs(afterVal-beforeVal-iDx)>=0.0000001) {
071                    sLog.error("-- value mischmatch (delta:"+(afterVal-beforeVal)+", value:"+iDx+")");
072                    sLog.error("  -- neighbour: "+n);
073                    sLog.error("  -- solution:  "+toString(afterValM, beforeValM));
074                }
075            } else {
076                getVariable().assign(iteration, getValue());
077            }
078        }
079        
080        
081        protected static String toString(double[] x) {
082            DecimalFormat df = new DecimalFormat("0.00");
083            StringBuffer s = new StringBuffer();
084            for (int i=0;i<x.length;i++) {
085                if (i>0) s.append(",");
086                s.append(df.format(x[i]));
087            }
088            return "["+s.toString()+"]";
089        }
090        
091        protected static String toString(double[] x, double[] y) {
092            DecimalFormat df = new DecimalFormat("0.00");
093            StringBuffer s = new StringBuffer();
094            for (int i=0;i<x.length;i++) {
095                if (i>0) s.append(",");
096                s.append(df.format(x[i]-y[i]));
097            }
098            return "["+s.toString()+"]";
099        }
100    
101        public String toString() {
102            return 
103                getVariable().getAssignment()+
104                " -> "+
105                getValue().toString()+
106                " / "+" (value:"+value()+")";
107        }
108        
109        public double value() {
110            return iValue;
111        }
112    }