/*======================================================================== Copyright (C) 2006 by Geir-Tore Lindsve, Torbjørn Meistad and Yngve Raudberget, hereby refered to as "the authors". All rights reserved Permission is hereby granted, without written agreement and without license or royalty fees, to use, reproduce, prepare derivative works, distribute, and display this software and its documentation for NONCOMMERCIAL RESEARCH AND EDUCATIONAL PURPOSES, provided that (1) the above copyright notice and the following two paragraphs appear in all copies of the source code and (2) redistributions, including without limitation binaries, reproduce these notices in the supporting documentation. IN NO EVENT SHALL THE AUTHORS, OR DISTRIBUTORS OF THIS SOFTWARE BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE AUTHORS OR ANY OF THE ABOVE PARTIES HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. THE AUTHORS SPECIFICALLY DISCLAIM ANY WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, AND THE AUTHORS AND DISTRIBUTORS HAVE NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. ========================================================================*/ using System; using System.Collections.Generic; using System.Collections; using System.Text; using Iesi.Collections; using Casper.Exceptions; using Casper.Data; namespace Casper.Algorithm { /// /// CaSPers default implementation of the IConsistent interface /// public class Consistent { private List rules; private LookAheadVarDom currAss; private LookAheadVarDom nextAss; private Hashtable assignedVars; /// /// Initializes a new instance of the class. /// /// The expressions to be used as rules. public Consistent(CSPExpressions expressions) { this.rules = expressions.WrappedExprList; } /// /// Verifies whether the assigned variables contains all the variables in the rule or not /// /// Set of variables in the current rule /// true if assigned variables contains all variables in "vars"; otherwise, false. public Boolean AssignedVarsContainsAll(Set vars) { foreach (int varID in vars) { if (!assignedVars.Contains(varID)) return false; } return true; } /// /// Main method for Consistency checks /// /// All assigned variables, including currAss and nextAss. Hashtable of LookAheadVarDom objects /// Current assignment /// Next assignment /// true if consistent; otherwise, false. /// public Boolean IsConsistent(Hashtable allAssignedVars, LookAheadVarDom currAss, LookAheadVarDom nextAss) { this.currAss = currAss; this.nextAss = nextAss; this.assignedVars = allAssignedVars; for (int i = 0; i < rules.Count; i++) { /* Checks to make sure that the assigned variables consists of at least all variables for the current rule expression, * and that the current rule either contains nextAss or is a unary constraint which restricts currAss. * If not, skip to the next rule expression */ if (AssignedVarsContainsAll(rules[i].VariablesInExpr) && (rules[i].VariablesInExpr.Contains(nextAss.VarID) || ((rules[i].VariablesInExpr.Count == 1) && (rules[i].VariablesInExpr.Contains(currAss.VarID))))) { try { if (rules[i].RuleExpression.ConsistentCheckExpression(this) == 0) return false; } catch (Exception e) //Makes sure that we handle unknown exceptions as a result of the expression checking (divide-by-zero, etc.) { throw new CasperException("Unknown exception while running consistency check", e); } } } return true; } /// /// Returns the currently selected value for the variable associated in the expression /// /// Current expression /// Integer value /// public int ConsistentCheckExpression(CSPExprVarInt rule) { LookAheadVarDom var = (LookAheadVarDom) assignedVars[rule.VarID]; if(var==null) throw new CasperException("Encountered an unassigned variable during consistency check"); return (int)var.SelectedValue; } /// /// Returns the currently selected value for the variable associated in the expression /// /// Current expression /// Integer value /// public int ConsistentCheckExpression(CSPExprVarBool rule) { LookAheadVarDom var = (LookAheadVarDom)assignedVars[rule.VarID]; if (var == null) throw new CasperException("Encountered an unassigned variable during consistency check"); return (int)var.SelectedValue; } /// /// Returns the currently selected value for the variable associated in the expression /// /// Current expression /// Integer value /// public int ConsistentCheckExpression(CSPExprVarEnum rule) { LookAheadVarDom var = (LookAheadVarDom)assignedVars[rule.VarID]; if (var == null) throw new CasperException("Encountered an unassigned variable during consistency check"); return (int)var.SelectedValue; } /// /// Returns the Int/Const value of the terminal expression /// /// Current expression /// Integer value public int ConsistentCheckExpression(CSPExprValue rule) { return rule.Value; } /// /// Returns the result of the negation. /// /// Current expression /// Integer value public int ConsistentCheckExpression(CSPExprNeg rule) { return Neg(rule.Left.ConsistentCheckExpression(this)); } /// /// Returns the result of the inversion. /// /// Current expression /// Integer value public int ConsistentCheckExpression(CSPExprNot rule) { return Not(rule.Left.ConsistentCheckExpression(this)); } /// /// Returns the result of binary expressions /// /// Current expression /// Integer value /// public int ConsistentCheckExpression(CSPExprBin rule) { switch (rule.Oper) { case StaticData.Operators.and: return And(rule.Left.ConsistentCheckExpression(this), rule.Right.ConsistentCheckExpression(this)); case StaticData.Operators.div: return Div(rule.Left.ConsistentCheckExpression(this), rule.Right.ConsistentCheckExpression(this)); case StaticData.Operators.eq: return Equal(rule.Left.ConsistentCheckExpression(this), rule.Right.ConsistentCheckExpression(this)); case StaticData.Operators.gt: return GreaterThan(rule.Left.ConsistentCheckExpression(this), rule.Right.ConsistentCheckExpression(this)); case StaticData.Operators.gte: return GreaterThanEqual(rule.Left.ConsistentCheckExpression(this), rule.Right.ConsistentCheckExpression(this)); case StaticData.Operators.impl: return Impl(rule.Left.ConsistentCheckExpression(this), rule.Right.ConsistentCheckExpression(this)); case StaticData.Operators.lt: return LessThan(rule.Left.ConsistentCheckExpression(this), rule.Right.ConsistentCheckExpression(this)); case StaticData.Operators.lte: return LessThanEqual(rule.Left.ConsistentCheckExpression(this), rule.Right.ConsistentCheckExpression(this)); case StaticData.Operators.minus: return Minus(rule.Left.ConsistentCheckExpression(this), rule.Right.ConsistentCheckExpression(this)); case StaticData.Operators.mod: return Mod(rule.Left.ConsistentCheckExpression(this), rule.Right.ConsistentCheckExpression(this)); case StaticData.Operators.ne: return NotEqual(rule.Left.ConsistentCheckExpression(this), rule.Right.ConsistentCheckExpression(this)); case StaticData.Operators.or: return Or(rule.Left.ConsistentCheckExpression(this), rule.Right.ConsistentCheckExpression(this)); case StaticData.Operators.plus: return Add(rule.Left.ConsistentCheckExpression(this), rule.Right.ConsistentCheckExpression(this)); case StaticData.Operators.times: return Times(rule.Left.ConsistentCheckExpression(this), rule.Right.ConsistentCheckExpression(this)); default: throw new CasperException("Encountered an unhandled operator type during consistency check: " + rule.Oper.ToString()); } } /* * * OPERATOR METHODS * */ /// /// Imply. /// /// First value. /// Second value. /// Result of in1 >> in2 private int Impl(int in1, int in2) { if (in1 != 0 && in2 == 0) return 0; return 1; } /// /// Greater Than. /// /// First value. /// Second value. /// Result of in1 > in2 private int GreaterThan(int in1, int in2) { if (in1 > in2) return 1; return 0; } /// /// Greater Than Or Equal. /// /// First value. /// Second value. /// Result of in1 >= in2 private int GreaterThanEqual(int in1, int in2) { if (in1 >= in2) return 1; return 0; } /// /// Less Than. /// /// First value. /// Second value. /// Result of in1 < in2 private int LessThan(int in1, int in2) { if (in1 < in2) return 1; return 0; } /// /// Less Than Or Equal. /// /// First value. /// Second value. /// Result of in1 <= in2 private int LessThanEqual(int in1, int in2) { if (in1 <= in2) return 1; return 0; } /// /// Equal. /// /// First value. /// Second value. /// Result of in1 = in2 private int Equal(int in1, int in2) { if (in1 != in2) return 0; return 1; } /// /// Not Equal. /// /// First value. /// Second value. /// Result of in1 != in2 private int NotEqual(int in1, int in2) { if (in1 != in2) return 1; return 0; } /// /// Addition. /// /// First value. /// Second value. /// Result of in1 + in2 private int Add(int in1, int in2) { return in1 + in2; } /// /// Subtraction. /// /// First value. /// Second value. /// Result of in1 - in2 private int Minus(int in1, int in2) { return in1 - in2; } /// /// Multiplication. /// /// First value. /// Second value. /// Result of in1 > in2 private int Times(int in1, int in2) { return in1 * in2; } /// /// Negation. /// /// Integer value to negate. /// -in1 private int Neg(int in1) { return in1 * -1; } /// /// Inversion. /// /// Integer value to invert. /// !in1 private int Not(int in1) { if (in1 == 0) return 1; else return 0; } /// /// Division. /// /// First value. /// Second value. /// Result of in1 / in2 private int Div(int in1, int in2) { return in1 / in2; } /// /// Modulo. /// /// First value. /// Second value. /// Result of in1 % in2 private int Mod(int in1, int in2) { return in1 % in2; } /// /// Boolean Or. /// /// First value. /// Second value. /// Result of in1 OR in2 private int Or(int in1, int in2) { if (in1 + in2 == 0) return 0; return 1; } /// /// Boolean And. /// /// First value. /// Second value. /// Result of in1 AND in2 private int And(int in1, int in2) { if (in1 + in2 >= 2) return 1; return 0; } /// /// Converts integers to boolean values /// /// Integer value to convert to bool. /// Boolean representation of in1 private int Int2Bool(int i) { if (i == 0) return 0; return 1; } } }