//$Header: /home/woru/CVSRepository-Diplom/diplom/yacs/src/YacsTester.java,v 1.12 2005/11/03 14:24:35 woru Exp $
import yacs.*;
import yacs.domain.*;
import yacs.exceptions.*;
import yacs.net.*;

import java.util.*;

import org.apache.log4j.*;

/**
 * <p>Klasse zum Testen verschiedener Funktionalitaeten von YACS.</p>
 *
 * <p>Copyright (C) 2005  Wolfgang Runte
 * <br><br>
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 * <br><br>
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 * <br><br>
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301
 * USA</p>
 *
 * @author Wolfgang Runte (woru@tzi.org)
 * @version YACS 0.1.1
 *
 * Last Change:
 * <br>by:   $Author: woru $
 * <br>date: $Date: 2005/11/03 14:24:35 $
 */
public class YacsTester {

// ********** private attributs **********

  /** Logger aktivieren: */
  private static Logger logger = Logger.getLogger("yacs");

  /** Dateipfad zu den Constraint-Loesungsstrategien. */
  private final String strategyPath = "yacs_strategies.xml";

  /** Instanz des YACS Constraint-Managers. */
  private final YacsConstraintManager ycm;

// ********** public attributs **********

// ********** private methods **********

  /**
   * Ein paar Testausgaben: Der Strategiename, das zugehoerigen Teilproblem, die
   * primitiven Constraint-Ausdruecke sowie die involvierten Variablen und deren
   * Domaenen.
   * @param strategyName String
   */
  private void printTestValues(String strategyName) {
    try {
      // Constraint-Netz unter Angabe des Strategienamens vom YCM holen:
      ConstraintNet constraintNet = this.ycm.getConstraintNet(strategyName);
      // Liste der vorhandenen Variablen des Teilproblems holen:
      List variablesList = constraintNet.getVariables();
      // Testausgaben:
      System.out.println("Strategie: '" + constraintNet.getStrategyName() + "'");
      System.out.println("Expression: " + constraintNet.getSubproblem());
      List exprList = constraintNet.getConstraints();
      System.out.println("Primitive Constraints: (" + exprList.size() + ")");
      for (int i = 0; i < exprList.size(); i++) {
        System.out.println(exprList.get(i));
      }
      System.out.println("Variablen: " + constraintNet.getVariables());
      System.out.println("Domaenen der Constraint-Variablen: (" +
                         variablesList.size() + ")");
      try {
        for (int i = 0; i < variablesList.size(); i++) {
          System.out.println(variablesList.get(i) + ": " +
                             this.ycm.
                             getVariableDomain((String)variablesList.get(i)));
        }
      } catch (VariableNotFoundException e) {
        e.printStackTrace();
      }
      System.out.println("Constraint-Netz -> " +
                         this.ycm.getConstraintNet(strategyName));
      System.out.println("Inkonsistenz: " + this.ycm.isInconsistent(strategyName));
    } catch (StrategyNotFoundException e) {
      e.printStackTrace();
    }
  }

  /**
   * Constraints unter Angabe des Namens der zu verwendenen Strategie zum YACS
   * Constraint-Manager (YCM) hinzufuegen.
   * @param strategyName String
   * @param constraintArray String[]
   */
  private void initConstraints(String strategyName, String[] constraintArray) {
    for (int i = 0; i < constraintArray.length; i++) {
      try {
        this.ycm.addConstraint(constraintArray[i], strategyName);
      } catch (ConstraintParserException e) {
        e.printStackTrace();
      } catch (StrategyNotFoundException e) {
        e.printStackTrace();
      }
    }
  }

// ********** public methods **********

  /**
   * NCSolverTest
   * @param init boolean
   */
  public void NCSolverTest(boolean init) {
    List variablesList;
    // Name der Strategie:
    String strategyName = "low_consistency";
    try {
      if (init) {
        System.out.println();
        System.out.println("Einfaches Problem zum Testen von Knotenkonsistenz:");
        System.out.println("==================================================");
        // Constraints spezifizieren:
        String constraintArray[] = new String[4];
        //constraintArray[0] = "x < y; y < z; z <= 2; 3 + y < 7;";
        constraintArray[0] = "x < y;";
        constraintArray[1] = "y < z;";
        constraintArray[2] = "z <= 2;";
        constraintArray[3] = "3 + y < 7;";
        // Constraints zum YCM hinzufuegen:
        this.initConstraints(strategyName, constraintArray);
        // Liste der Variablen der Strategie bzw. des Constraint-Netzes holen:
        variablesList = this.ycm.getVariables(strategyName);
        // Wertebereiche der Constraint-Variablen setzen:
        try {
          for (int i = 0; i < variablesList.size(); i++) {
            this.ycm.setVariableDomain((String)variablesList.get(i),
                                       new NumericFDDomain(0, 9));
          }
        } catch (VariableNotFoundException e) {
          e.printStackTrace();
        }
        // Testausgaben:
        this.printTestValues(strategyName);
      } else {
        System.out.println();
        System.out.println("Ergebnis fuer Knotenkonsistenz:");
        System.out.println("===============================");
        // Testausgaben:
        this.printTestValues(strategyName);
        // Ergebnis ausgeben:
        if (!this.ycm.hasFalseDomain(strategyName)) {
          System.out.println("\nErgebnis ist knotenkonsistent!");
        } else {
          System.out.println("\nKnotenkonsistenz nicht herstellbar!");
        }
      }
    } catch (StrategyNotFoundException e) {
      e.printStackTrace();
    }
  }

  /**
   * AC3SolverTest
   * @param init boolean
   */
  public void AC3SolverTest(boolean init) {
    List variablesList;
    // Name der Strategie:
    String strategyName = "medium_consistency";
    try {
      if (init) {
        System.out.println();
        System.out.println("Kartenfaerbeproblem fuer eine Australienkarte:");
        System.out.println("==============================================");
        // Constraints spezifizieren:
        String constraintArray[] = new String[9];
//        constraintArray[0] = "WA != NT; WA != SA; NT != SA; NT != Q; SA != Q; SA != NSW; SA != V; Q != NSW; NSW != V; T = T;";
        constraintArray[0] = "WA != NT;";
        constraintArray[1] = "WA != SA;";
        constraintArray[2] = "NT != SA;";
        constraintArray[3] = "NT != Q;";
        constraintArray[4] = "SA != Q;";
        constraintArray[5] = "SA != NSW;";
        constraintArray[6] = "SA != V;";
        constraintArray[7] = "Q != NSW;";
//        constraintArray[8] = "NSW != V;";
        constraintArray[8] = "T = T;";
        // Constraints zum YCM hinzufuegen:
        this.initConstraints(strategyName, constraintArray);
        // Liste der Variablen der Strategie bzw. des Constraint-Netzes holen:
        variablesList = this.ycm.getVariables(strategyName);
        // Wertebereiche der Constraint-Variablen setzen:
        SymbolicFDDomain domain;
        try {
          for (int i = 0; i < variablesList.size(); i++) {
//          this.ycm.setVariableDomain(variablesList.get(i).toString(), new NumericFDDomain(0,2));
            domain = new SymbolicFDDomain();
            domain.add(new SymbolicFDElement("rot"));
            domain.add(new SymbolicFDElement("gruen"));
            domain.add(new SymbolicFDElement("blau"));
            this.ycm.setVariableDomain((String)variablesList.get(i), domain);
          }
          // Die Einschraenkungen vornehmen, um auf Inkonsistenzen pruefen zu
          // koennen:
//          this.ycm.setVariableDomain("WA", new NumericFDDomain(0));
//          this.ycm.setVariableDomain("V", new NumericFDDomain(2));
          this.ycm.setVariableDomain("WA", new SymbolicFDDomain("rot"));
//          this.ycm.setVariableDomain("V", new SymbolicFDDomain("blau"));
        } catch (VariableNotFoundException e) {
          e.printStackTrace();
        }
        // Testausgaben:
        this.printTestValues(strategyName);
      } else {
        System.out.println();
        System.out.println("Ergebnis fuer Kartenfaerbeproblem:");
        System.out.println("==================================");
        // Testausgaben:
        this.printTestValues(strategyName);
        // Ergebnis ausgeben:
        if (!this.ycm.hasFalseDomain(strategyName)) {
          System.out.println("\nErgebnis ist kantenkonsistent!");
        } else {
          System.out.println("\nKantenkonsistenz nicht herstellbar!");
        }
      }
    } catch (StrategyNotFoundException e) {
      e.printStackTrace();
    }
  }

  /**
   * SingleSolutionBTSolverTest
   * @param init boolean
   */
  public void SingleSolutionBTSolverTest(boolean init) {
    List variablesList;
    // Name der Strategie:
    String strategyName = "simple_search";
    try {
      if (init) {
        System.out.println();
        System.out.println("Simple Search:");
        System.out.println("==============");
        // Constraints spezifizieren:
        String constraintArray[] = new String[2];
//        constraintArray[0] = "X < Y; Y < Z;";
        constraintArray[0] = "X < Y;";
        constraintArray[1] = "Y < Z;";
        // Constraints zum YCM hinzufuegen:
        this.initConstraints(strategyName, constraintArray);
        // Liste der Variablen der Strategie bzw. des Constraint-Netzes holen:
        variablesList = this.ycm.getVariables(strategyName);
        // Wertebereiche der Constraint-Variablen setzen:
        try {
          for (int i = 0; i < variablesList.size(); i++) {
            this.ycm.setVariableDomain((String)variablesList.get(i),
                                       new NumericFDDomain(1, 2));
          }
        } catch (VariableNotFoundException e) {
          e.printStackTrace();
        }
        // Testausgaben:
        this.printTestValues(strategyName);
      } else {
        System.out.println();
        System.out.println("Ergebnis fuer Simple Search:");
        System.out.println("============================");
        // Testausgaben:
        this.printTestValues(strategyName);
        // Ergebnis ausgeben:
        try {
          if (this.ycm.hasSolutions(strategyName)) {
            System.out.println("\nLoesung(en):" +
                               this.ycm.getSolutions(strategyName));
          } else {
            System.out.println(
              "\nEs konnte keine Loesung fuer das Problem ermittelt werden.");
          }
        } catch (StrategyNotFoundException e) {
          e.printStackTrace();
        }
      }
    } catch (StrategyNotFoundException e) {
      e.printStackTrace();
    }
  }

  /**
   * BacktrackingSolverTest
   * @param init boolean
   */
  public void BacktrackingSolverTest(boolean init) {
    List variablesList;
    // Name der Strategie:
    String strategyName = "search";
    try {
      if (init) {
        System.out.println();
        System.out.println("Smuggler's Knapsack (1):");
        System.out.println("========================");
        // Constraints spezifizieren:
        String constraintArray[] = new String[2];
//        constraintArray[0] = "4*W + 3*P + 2*C <= 9; 15*W + 10*P + 7*C >=30;";
        constraintArray[0] = "4*W + 3*P + 2*C <= 9;";
        constraintArray[1] = "15*W + 10*P + 7*C >=30;";
        // Constraints zum YCM hinzufuegen:
        this.initConstraints(strategyName, constraintArray);
        // Liste der Variablen der Strategie bzw. des Constraint-Netzes holen:
        variablesList = this.ycm.getVariables(strategyName);
        // Wertebereiche der Constraint-Variablen setzen:
        try {
          for (int i = 0; i < variablesList.size(); i++) {
            this.ycm.setVariableDomain((String)variablesList.get(i),
                                       new NumericFDDomain(0, 9));
          }
        } catch (VariableNotFoundException e) {
          e.printStackTrace();
        }
        // Testausgaben:
        this.printTestValues(strategyName);
      } else {
        System.out.println();
        System.out.println("Ergebnis fuer Smuggler's Knapsack (1):");
        System.out.println("======================================");
        // Testausgaben:
        this.printTestValues(strategyName);
        // Ergebnis ausgeben:
        try {
          if (this.ycm.hasSolutions(strategyName)) {
            System.out.println("\nLoesung(en):" +
                               this.ycm.getSolutions(strategyName));
          } else {
            System.out.println(
              "\nEs konnte keine Loesung fuer das Problem ermittelt werden.");
          }
        } catch (StrategyNotFoundException e) {
          e.printStackTrace();
        }
      }
    } catch (StrategyNotFoundException e) {
      e.printStackTrace();
    }
  }

  /**
   * MAC3SolverTest
   * @param init boolean
   */
  public void MAC3SolverTest(boolean init) {
    List variablesList;
    // Name der Strategie:
    String strategyName = "search_with_look-ahead";
    try {
      if (init) {
        System.out.println();
        System.out.println("Smuggler's Knapsack (2):");
        System.out.println("========================");
        // Constraints spezifizieren:
        String constraintArray[] = new String[2];
//        constraintArray[0] = "4*W + 3*P + 2*C <= 9; 15*W + 10*P + 7*C >=30;";
        constraintArray[0] = "4*W + 3*P + 2*C <= 9;";
        constraintArray[1] = "15*W + 10*P + 7*C >=30;";
        // Constraints zum YCM hinzufuegen:
        this.initConstraints(strategyName, constraintArray);
        // Liste der Variablen der Strategie bzw. des Constraint-Netzes holen:
        variablesList = this.ycm.getVariables(strategyName);
        // Wertebereiche der Constraint-Variablen setzen:
        try {
          for (int i = 0; i < variablesList.size(); i++) {
            this.ycm.setVariableDomain((String)variablesList.get(i),
                                       new NumericFDDomain(0, 9));
          }
        } catch (VariableNotFoundException e) {
          e.printStackTrace();
        }
        // Testausgaben:
        this.printTestValues(strategyName);
      } else {
        System.out.println();
        System.out.println("Ergebnis fuer Smuggler's Knapsack (2):");
        System.out.println("=======================================");
        // Testausgaben:
        this.printTestValues(strategyName);
        // Ergebnis ausgeben:
        try {
          if (this.ycm.hasSolutions(strategyName)) {
            System.out.println("\nLoesung(en):" +
                               this.ycm.getSolutions(strategyName));
          } else {
            System.out.println(
              "\nEs konnte keine Loesung fuer das Problem ermittelt werden.");
          }
        } catch (StrategyNotFoundException e) {
          e.printStackTrace();
        }
      }
    } catch (StrategyNotFoundException e) {
      e.printStackTrace();
    }
  }

  /**
   * HullConsistencySolverTest
   * @param init boolean
   */
  public void HullConsistencySolverTest(boolean init) {
    List variablesList;
    // Name der Strategie:
    String strategyName = "interval_consistency";
    try {
      if (init) {
        System.out.println();
        System.out.println("Einfaches Problem zum Testen von Hull-Konsistenz:");
        System.out.println("=================================================");
        // Constraints spezifizieren:
        String constraintArray[] = new String[2];
//      constraintArray[0] = "A = [150,150] * B; B = A / [150,150];";
//      constraintArray[0] = "A = [150,150] * B;";
//      constraintArray[1] = "B = A / [150,150];";
//      constraintArray[0] = "v1 + v2 = v3; v2 = v3 - v1; v1 = v3 - v2; v2 <= v1; v1 >= v2;";
        constraintArray[0] = "v1 + v2 = v3; v2 = v3 - v1; v1 = v3 - v2;";
//      constraintArray[1] = "v2 <= v1; v1 >= v2;";
        constraintArray[1] = "v2 = v1; v1 = v2;";
/*      constraintArray[0] = "v2 < v1; v1 > v2;";
        constraintArray[1] = "v1 < v2; v2 > v1;";*/
/*      constraintArray[0] = "v1 = [3,3];";
        constraintArray[1] = "v1 = [5,5];";*/
        // Constraints zum YCM hinzufuegen:
        this.initConstraints(strategyName, constraintArray);
        // Wertebereiche der Constraint-Variablen setzen:
        try {
//          this.ycm.setVariableDomain("A", new IntervalDomain(3600,6000));
//          this.ycm.setVariableDomain("B", new IntervalDomain(24,40));
          this.ycm.setVariableDomain("v1", new IntervalDomain(2, 12));
          this.ycm.setVariableDomain("v2", new IntervalDomain(4, 9));
          this.ycm.setVariableDomain("v3", new IntervalDomain(2, 8));
        } catch (VariableNotFoundException e) {
          e.printStackTrace();
        }
        // Testausgaben:
        this.printTestValues(strategyName);
      } else {
        System.out.println();
        System.out.println("Ergebnis fuer Hull-Konsistenz:");
        System.out.println("==============================");
        // Testausgaben:
        this.printTestValues(strategyName);
        // Ergebnis ausgeben:
        if (!this.ycm.hasFalseDomain(strategyName)) {
          System.out.println("\nErgebnis ist konsistent!");
        } else {
          System.out.println("\nKonsistenz nicht herstellbar!");
        }
      }
    } catch (StrategyNotFoundException e) {
      e.printStackTrace();
    }
  }

  /**
   * Konstruktor
   */
  public YacsTester() {
    // Den YACS Constraint-Manager mit dem Pfad zu den
    // Constraint-Loesungsstrategien instantiieren:
    this.ycm = new YacsConstraintManagerImpl(this.strategyPath);
    // Loglevel setzen (moegliche Level: ALL, DEBUG, INFO, WARN, ERROR, FATAL):
    this.logger.setLevel(Level.OFF);

    // Testprobleme initialisieren:
    this.NCSolverTest(true);
    this.AC3SolverTest(true);
    this.SingleSolutionBTSolverTest(true);
    this.BacktrackingSolverTest(true);
    this.MAC3SolverTest(true);
    this.HullConsistencySolverTest(true);

    // Constraint-Loesungsprozess initiieren:
    System.out.println("\n");
    System.out.println("**************************************");
    System.out.println("* Starten der Constraint-Auswertung! *");
    System.out.println("**************************************");
    System.out.println();
    this.ycm.evaluate();
    // Ergebnisse ausgeben:
    this.NCSolverTest(false);
    this.AC3SolverTest(false);
    this.SingleSolutionBTSolverTest(false);
    this.BacktrackingSolverTest(false);
    this.MAC3SolverTest(false);
    this.HullConsistencySolverTest(false);

    // Einige Constraints hinzufuegen:
    System.out.println("\n");
    System.out.println("Fuege zusaetzliche Constraints hinzu:");
    System.out.println("=====================================");
    try {
      this.ycm.addConstraint("z > 2;", "low_consistency");
      this.ycm.addConstraint("NSW != V;", "medium_consistency");
      this.ycm.addConstraint("W > 1;", "search");
      this.ycm.addConstraint("W > 1;", "search_with_look-ahead");
//      this.ycm.addConstraint("C > 0;", "search");
//      this.ycm.addConstraint("C > 0;", "search_with_look-ahead");
//      this.ycm.addConstraint("P > 1;", "search");
//      this.ycm.addConstraint("P > 1;", "search_with_look-ahead");
      this.ycm.addConstraint("v1 = [5,5];", "interval_consistency");
    } catch (ConstraintParserException e) {
      e.printStackTrace();
    } catch (StrategyNotFoundException e) {
      e.printStackTrace();
    }
    // Einige zusaetzliche Wertebereichseinschraenkungen vornehmen:
    System.out.println("\n");
    System.out.println("Nehme Aenderungen an den Wertebereichen vor:");
    System.out.println("============================================");
    try {
      System.out.println("Variable: 'V' -> Wert: 'blau'");
      this.ycm.setVariableDomain("V", new SymbolicFDDomain("blau"));
      System.out.println("Variable: 'W' -> Wert: '2'");
      this.ycm.setVariableDomain("W", new NumericFDDomain(2));
      System.out.println("Variable: 'Z' -> Wert: '1' bis '3'");
      this.ycm.setVariableDomain("Z", new NumericFDDomain(1, 3));
//      this.ycm.setVariableDomain("A", new IntervalDomain(3600,3600));
//      this.ycm.setVariableDomain("B", new IntervalDomain(24,24));
    } catch (VariableNotFoundException e) {
      e.printStackTrace();
    }
    // Constraint-Loesungsprozess initiieren:
    System.out.println("\n");
    System.out.println("**************************************************");
    System.out.println("* Nochmaliges Starten der Constraint-Auswertung! *");
    System.out.println("**************************************************");
    System.out.println();
    this.ycm.evaluate();
    // Ergebnisse ausgeben:
    this.NCSolverTest(false);
    this.AC3SolverTest(false);
    this.SingleSolutionBTSolverTest(false);
    this.BacktrackingSolverTest(false);
    this.MAC3SolverTest(false);
    this.HullConsistencySolverTest(false);

  }

  public static void main(String[] args) {
    YacsTester yacsTester = new YacsTester();
  }

}

/*
 * $Log: YacsTester.java,v $
 * Revision 1.12  2005/11/03 14:24:35  woru
 * <Kein Kommentar eingegeben>
 *
 * Revision 1.11  2005/11/02 16:35:40  woru
 * <Kein Kommentar eingegeben>
 *
 * Revision 1.10  2005/10/29 23:06:31  woru
 * <Kein Kommentar eingegeben>
 *
 * Revision 1.9  2005/09/16 00:22:06  woru
 * <Kein Kommentar eingegeben>
 *
 * Revision 1.8  2005/09/14 19:43:31  woru
 * <Kein Kommentar eingegeben>
 *
 * Revision 1.7  2005/09/09 20:26:41  woru
 * <Kein Kommentar eingegeben>
 *
 * Revision 1.6  2005/09/09 11:50:20  woru
 * <Kein Kommentar eingegeben>
 */
