/*======================================================================== 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.Text; using System.Collections; using System.Windows.Forms; using System.IO; using System.Threading; using System.Xml; using System.Xml.Schema; using System.Reflection; using CLab; using CLab.Exceptions; using CLab.CSP; using CLab.Data; using CLab.Parsers; using Casper.Exceptions; using ClabGui.Exceptions; namespace ClabGui { /// /// This class is working between CLab and the GUI class, . /// The searching part is run in its own thread, so the application won't hang during a heavy search. /// public class Program { private Clab clab; private MainGui mainGui; private Hashtable varNameToGuiId; private Hashtable guiIdToVarName; private String problemFilename = ""; private CLabTextParser textParser; private Thread clabThread; private Boolean clabThreadPaused = false; private int guiId; private String domainVal; private CLab.CLabModus modus = CLabModus.csp_modus; private CspVariableOrdering cspVariableOrdering = CspVariableOrdering.vo_static; private BddCompileMethod bddCompileMethod = BddCompileMethod.cm_static; /// /// Initializes a new instance of the class. /// public Program() { textParser = new CLabTextParser(); Application.EnableVisualStyles(); Application.SetCompatibleTextRenderingDefault(false); mainGui = new MainGui(this); Application.Run(mainGui); } /// /// Initializes a new instance of the class. /// /// Name of the file to be opened. public Program(String fileName) { textParser = new CLabTextParser(); Application.EnableVisualStyles(); Application.SetCompatibleTextRenderingDefault(false); mainGui = new MainGui(this); mainGui.OpenFile(fileName); Application.Run(mainGui); } /// /// Gets or sets the problem filename. /// /// The problem filename. public String ProblemFilename { get { return problemFilename; } set { problemFilename = value; } } /// /// Strips the path from filename. /// /// A that represents the filename with full path /// A that represents the filename without the path public String StripPathFromFilename(String filename) { if (filename != "") { String pf = filename; int pfi = pf.LastIndexOf("\\"); String filenameWithoutPath = pf.Substring(pfi + 1, pf.Length - pfi - 1); return filenameWithoutPath; } else return ""; } /// /// Gets or sets the modus to use, BDD if modus = 0 or CSP if modus = 1. /// /// An int which represents the modus to use. public CLabModus Modus { get { return modus; } set { modus = value; } } /// /// Method for checking if CLab is running a search. /// /// true if CLab is running a search, otherwise, false. public Boolean ClabThreadIsAlive() { if (clabThread != null) return clabThread.IsAlive; return false; } /// /// Pauses the CLab thread if running, and resumes if paused. /// /// true if CLab thread is paused, otherwise, false. public Boolean PauseClabThreadIfRunning() { if (ClabThreadIsAlive()) { if (clabThreadPaused) { clabThread.Resume(); clabThreadPaused = false; return false; } else { clabThread.Suspend(); clabThreadPaused = true; return true; } } return false; } /// /// Stops the clab thread if running. /// public void StopClabThreadIfRunning() { if (clabThread!=null && clabThread.IsAlive) { if (clabThreadPaused) PauseClabThreadIfRunning(); clabThread.Abort(); } } /// /// Starts a new CLab instance, and fills the GUI with initial data. /// public Boolean StartClab() { varNameToGuiId = new Hashtable(); guiIdToVarName = new Hashtable(); try { if (problemFilename != "" && problemFilename.ToLower().EndsWith(".xml")) { clab = new Clab(problemFilename); } else { String data = ReadTextFromFile(problemFilename); MemoryStream mStream = null; try { mStream = textParser.CPtoXML(data); } catch (Exception e) { mainGui.ShowExceptionInGui(e); return false; } if (mStream != null) { mStream.Position = 0; clab = new Clab(mStream); } } clab.SetCSPVariableOrdering(cspVariableOrdering); clab.SetBddCompileMethod(bddCompileMethod); int[] bddSettings = mainGui.GetBDDInitialSettings(); if (bddSettings != null) { clab.Initdbcache = bddSettings[0]; clab.Initbddnodes = bddSettings[1]; clab.Maxincrease = bddSettings[2]; } ValidDomains originalDomains = clab.InitializeProblemSolver(modus); AddDataToGui(originalDomains); return true; } catch (Exception e) { mainGui.ShowExceptionInGui(e); return false; } } /// /// Starts the clab initial search thread. /// public void StartClabInitialSearchThread() { ThreadStart tstart = new ThreadStart(StartClabInitialSearch); clabThread = new Thread(tstart); clabThread.IsBackground = true; clabThread.Start(); } /// /// Starts the clab initial search, and updates the GUI with valid domaines. /// private void StartClabInitialSearch() { try { mainGui.SetupStatusBar(clab.StatusUpdateCount()); clab.StatusEvent -= new Clab.StatusEventHandler(statusChanged); clab.StatusEvent += new Clab.StatusEventHandler(statusChanged); DateTime start = System.DateTime.Now; ValidDomains vd = clab.GetValidDomains(); DateTime stop = System.DateTime.Now; mainGui.SetStatusMessage("Run time: " + stop.Subtract(start)); UpdateGuiDomains(vd); } catch (ClabException e) { mainGui.ShowExceptionInGui(e); } catch (CasperException e) { mainGui.ShowExceptionInGui(e); } } /// /// Sets the CSP variable ordering. /// /// The variable ordering. public void SetCSPVariableOrdering(CspVariableOrdering varOrder) { cspVariableOrdering = varOrder; if (clab != null) { clab.SetCSPVariableOrdering(varOrder); } } /// /// Sets the BDD compile method. /// /// The compile method. public void SetBDDCompileMethod(BddCompileMethod compileMethod) { bddCompileMethod = compileMethod; } /// /// Updates the GUI with new status during search. /// /// The status value. private void statusChanged(int value) { mainGui.StatusBarStep(value); } /// /// Adds the variable and domaine values data to GUI. /// /// The vd. public void AddDataToGui(ValidDomains vd) { List vDoms = vd.ValidDoms; for (int i=vDoms.Count-1; i>=0; i--) { ValidDomain validDomain = vDoms[i]; List vDomainValues = validDomain.Domains; mainGui.AddVar(validDomain.VarName, vDomainValues, i); varNameToGuiId[validDomain.VarName] = i; guiIdToVarName[i] = validDomain.VarName; } } /// /// Starts the clab value chosen search thread. /// /// The GUI variable ID, for chosen variable. /// The chosen domain value. public void ValueChosenSearchThread(int guiId, String domainVal) { this.guiId = guiId; this.domainVal = domainVal; ThreadStart tStart = new ThreadStart(ValueChosenSearch); clabThread = new Thread(tStart); clabThread.IsBackground = true; clabThread.Start(); } /// /// Runs the value chosen search, and updates the GUI with the valid domains. /// private void ValueChosenSearch() { try { mainGui.SetupStatusBar(clab.StatusUpdateCount()); String varName = (String)guiIdToVarName[guiId]; clab.StatusEvent -= new Clab.StatusEventHandler(statusChanged); clab.StatusEvent += new Clab.StatusEventHandler(statusChanged); DateTime start = System.DateTime.Now; ValidDomains vd = clab.GetValidDomainsExtraRule(varName, domainVal); DateTime stop = System.DateTime.Now; mainGui.SetStatusMessage("Run time: " + stop.Subtract(start)); UpdateGuiDomains(vd); } catch (Exception e) { mainGui.ShowExceptionInGui(e); } } /// /// Updates the GUI domains with the valid domains. /// /// The valid domaines, . public void UpdateGuiDomains(ValidDomains vd) { List validDoms = vd.ValidDoms; for (int i = 0; i < validDoms.Count; i++) { List domainV = validDoms[i].Domains; int guiId = (int)varNameToGuiId[validDoms[i].VarName]; mainGui.UpdateDomainV(guiId, domainV); } if (validDoms[0] != null && validDoms[0].Domains.Count == 0) mainGui.ShowMessageBox("No valid solutions found!"); } /// /// Saves the file. /// /// The text. public void SaveFile(String text) { SaveFileAs(problemFilename, text); } /// /// Saves the file as. /// /// Name of the file. /// The text. public void SaveFileAs(String fileName, String text) { try { if (fileName.ToLower().EndsWith(".xml")) { WriteCPToXml(fileName, text); } else { WriteTextFile(fileName, text); } problemFilename = fileName; } catch (Exception e) { mainGui.ShowExceptionInGui(e); } } /// /// Writes a xml file. Writes the CP text to XML. /// /// Name of the file. /// The CP text. public void WriteCPToXml(String fileName, String text) { MemoryStream memStream = null; try { memStream = textParser.CPtoXML(text); } catch (Exception) { if(memStream != null) memStream.Close(); throw; } FileStream fs = new FileStream(fileName, FileMode.Create); try{ memStream.WriteTo(fs); fs.Flush(); memStream.Close(); } catch (Exception) { throw; } finally { fs.Close(); } } /// /// Writes a text file. /// /// Name of the file. /// The text. public void WriteTextFile(String fileName, String text) { StreamWriter writer = new StreamWriter(fileName); try { writer.Write(text); writer.Flush(); } catch (Exception) { throw; } finally { writer.Close(); } } /// /// Returns the content of a text file /// /// The file to get content from /// String representation of file content public String OpenFile(String fileName) { problemFilename = ""; String data = ""; try { if (fileName.ToLower().EndsWith(".xml")) { CLabTextParser parser = new CLabTextParser(); data = parser.XMLtoCP(fileName); problemFilename = fileName; } else { data = ReadTextFromFile(fileName); problemFilename = fileName; } } catch (System.IO.IOException e) { mainGui.ShowExceptionInGui(e); } catch (System.OutOfMemoryException e) { mainGui.ShowExceptionInGui(e); } catch (ClabException e) { mainGui.ShowExceptionInGui(e); } return data; } /// /// Sets the CLab reference to null. /// public void StopClab() { clab = null; } /// /// Reads the text from a file. /// /// Name of the file. /// public String ReadTextFromFile(String fileName) { StreamReader reader = null; try { reader = new StreamReader(fileName); String data = ""; data = reader.ReadToEnd(); return data; } catch (Exception e) { throw e; } finally { if(reader!=null) reader.Close(); } } } }