Optika GUI Toolik Version of the Day
example/DependencyExample/main.cpp
Go to the documentation of this file.
00001 // @HEADER
00002 // ***********************************************************************
00003 // 
00004 //         Optika: A Tool For Developing Parameter Obtaining GUIs
00005 //                Copyright (2009) Sandia Corporation
00006 // 
00007 // Under terms of Contract DE-AC04-94AL85000, with Sandia Corporation, the 
00008 // U.S. Government retains certain rights in this software.
00009 // 
00010 // This library is free software; you can redistribute it and/or modify
00011 // it under the terms of the GNU Lesser General Public License as
00012 // published by the Free Software Foundation; either version 2.1 of the
00013 // License, or (at your option) any later version.
00014 //  
00015 // This library is distributed in the hope that it will be useful, but
00016 // WITHOUT ANY WARRANTY; without even the implied warranty of
00017 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00018 // Lesser General Public License for more details.
00019 //  
00020 // You should have received a copy of the GNU Lesser General Public
00021 // License along with this library; if not, write to the Free Software
00022 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
00023 // USA
00024 // Questions? Contact Kurtis Nusbaum (klnusbaum@gmail.com) 
00025 // 
00026 // ***********************************************************************
00027 // @HEADER
00028 #include "Optika_GUI.hpp"
00029 #include "Optika_SpecificParameterEntryValidators.hpp"
00030 #include "Teuchos_StandardParameterEntryValidators.hpp"
00031 #include "Optika_StandardDependencies.hpp"
00032 #include "Optika_DependencySheet.hpp"
00033 #include "Teuchos_FancyOStream.hpp"
00034 #include "Teuchos_VerboseObject.hpp"
00035 #include "Teuchos_XMLParameterListHelpers.hpp"
00036 
00037 int main(){
00038   /*
00039    * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! 
00040    * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!              ATTENTION              !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
00041    * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
00042    * !!!!   PLEASE VIEW THE BASIC EXAMPLE FIRST BEFORE READING THIS EXAMPLE. IT PROVIDES FUNDAMENTAL    !!!! 
00043    * !!!!   KNOWLEDGE THAT WILL BE VERY HELPFUL IN UNDERSTANDING THIS EXAMPLE.                          !!!!
00044    * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
00045    * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
00046    */ 
00047 
00048 
00049   /*
00050    * One of the most powerful features of the Optika package is it's ability to understand Dependencies
00051    * between various parameters. In order to take advantage of this capability you need to use the new 
00052    * "DependencySheet" class. For the most part, everything is still the same as before, and we do initial setup 
00053    * just like we did in the basic example. But now, we will also create our own DependencySheet.
00054    *
00055    */
00056   Teuchos::RCP<Teuchos::ParameterList> My_deplist = Teuchos::RCP<Teuchos::ParameterList>(new Teuchos::ParameterList);
00063   Teuchos::RCP<Optika::DependencySheet> depSheet1 =
00064     Teuchos::RCP<Optika::DependencySheet>(new Optika::DependencySheet(My_deplist, "My dep sheet"));
00065 
00066 
00067   /*
00068    * We'll start off by adding a few parameters. Pretty basic stuff.
00069    */
00070   Teuchos::Array<int> cheeseArray(10, 0);
00071   My_deplist->set("Cheese array stuff:", cheeseArray, "Array stuff");
00072   My_deplist->set("Max Iters", 1550, "Determines the maximum number of iterations in the solver");
00073   My_deplist->set("Tolerance", 1e-10, "The tolerance used for the convergence check");
00074   My_deplist->set("ShowPrecs", false, "Whether or not to show the preconditioners");
00075   Teuchos::ParameterList&
00076     Prec_List0 = My_deplist->sublist("Preconditioner",false,"Sublist that defines the preconditioner.");
00077 
00078   Prec_List0.set("Type", "ILU", "The tpye of preconditioner to use");
00079   Prec_List0.set("Drop Tolerance", 1e-3
00080                 ,"The tolerance below which entries from the\nfactorization are left out of the factors.");
00081 
00082   /*
00083    * Here we create a Dependency. There are several different types of dependencies but they all follow the 
00084    * same general outline: A dependent (which can be a parameter or parameter list) is dependent upon a 
00085    * dependee (which is always a non-array parameter). Different dependencies usually have different 
00086    * requirements of their dependee and dependent. So be sure to check a dependecies documentation if you're 
00087    * at all unsure whether or not you're using one correctly. Also, if you use a dependency incorrectly, 
00088    * you'll be notified by an error and the GUI will never execute. It's always important to make sure the 
00089    * GUI can at least run. Most errors that result from improperly formed dependencies will be caught before 
00090    * the user ever sees the GUI.
00091    *
00092    * Below is a bool visual dependency. What this means is the dependent's visibility to the user
00093    * is determined by the dependee's boolean value. Here the dependent is the ParameterList "Preconditioner".
00094    * The dependee is a boolean parameter called ShowPrec. We only want the Preconditioner ParameterList to show 
00095    * if the ShowPrecs parameter is set to true, so we give the boolean value of "true" as the showIf argument.
00096    * We also specify the parent parameter lists of both the dependent and the dependee.
00097    *
00098    * Note how both the Preconditioner sublist and ShowPrecs parameter are located in our "Root List" (which also
00099    * happens to be their parent ParameterList).
00100    *
00101    * If we were to write out this dependency as a sentance, it would read like this:
00102    * Only show the Preconditioner list if the ShowPrecs parameter is set to true.
00103    */
00104   Teuchos::RCP<Optika::BoolVisualDependency> precDep1 =
00105     Teuchos::RCP<Optika::BoolVisualDependency>(
00106       new Optika::BoolVisualDependency(
00107   "ShowPrecs",
00108   My_deplist,
00109         "Preconditioner",
00110   My_deplist,
00111   true));
00112 
00113   /*
00114    * Once we have created the depenency we add it to our dependency sheet using the addDependency function.
00115    * Dependencies can also be removed using the removeDependency function.
00116    */
00117   depSheet1->addDependency(precDep1);
00118 
00119 
00120   /*
00121    * Next we'll add two more parameters
00122    */
00123   My_deplist->set(
00124     "Favorite Cheese",
00125   "American",
00126   "Your favorite type of cheese");
00127   My_deplist->set("Swiss rating", 0, "How you rate swiss on a scail of 1 to 10");
00128 
00129   /*
00130    * Here we are creating a StringVisualDependency. The dependent this time is a parameter called Swiss rating. We only want
00131    * the swiss rating parameter to show if the Favorite Cheese parameter has the value Swiss. So we make Favorite Cheese the
00132    * dependee, set the desired value to Swiss, and the showIf argument to true. If we were to state this dependency as a
00133    * sentence it would read something like this:
00134    * Show the "Swiss rating" parameter when the "Favorite Cheese" parameter has the value "Swiss".
00135    */
00136    Teuchos::RCP<Optika::StringVisualDependency> swissDep1 = 
00137       Teuchos::RCP<Optika::StringVisualDependency>(
00138         new Optika::StringVisualDependency(
00139     "Favorite Cheese",
00140     My_deplist,
00141     "Swiss rating",
00142     My_deplist,
00143     "Swiss",
00144     true));
00145 
00146   /*
00147    * We then add the dependency.
00148    */
00149    depSheet1->addDependency(swissDep1);
00150 
00151   /*
00152    * Here we add two more parameters.
00153    */
00154    My_deplist->set("No awesome param", true, "Whether or not the awesome parameter should be shown");
00155    My_deplist->set("Awesomeness", 10, "How awesome you think dep lists are.");
00156 
00157   /*
00158    * Some times you only want a dependent to be shown when another parameter is NOT equal to a value.
00159    * Here the dependent is the Awesomeness parameter and we only want it to be shown when the No awesome param
00160    * is equal to false. So we pass false as the showIf argument. As a sentance, the dependnecy would read
00161    * like this:
00162    * Only show the "Awesomeness" parameter when the "No awesome param" is false.
00163    */
00164   Teuchos::RCP<Optika::BoolVisualDependency> awesomeDep1 =
00165     Teuchos::RCP<Optika::BoolVisualDependency>( new Optika::BoolVisualDependency(
00166       "No awesome param",
00167       My_deplist,
00168       "Awesomeness",
00169       My_deplist,
00170       false));
00171 
00172   /*
00173    * Then add the dependency to the dependency sheet.
00174    */
00175   depSheet1->addDependency(awesomeDep1);
00176 
00177 
00178   /*
00179    * Lets make a sublist to put into our "Root List".
00180    */
00181   Teuchos::ParameterList& waterList = My_deplist->sublist("Water", false, "A sublist about a lovely liquid.");
00182 
00183   /*
00184    * And let's put a couple parameters in the sublist.
00185    */
00186   waterList.set("Number Of Buckets", 3, "How many buckets we have");
00187   waterList.set("Amount in Buckets", Teuchos::Array<double>(3, 2.5), "How much water is in each bucket");
00188 
00189   /*
00190    * Obviously the number of buckets we have is going to affect the length of our array. If the number of
00191    * buckets gets changed to 5, we'll need an array length of 5. To solve this problem we'll use a
00192    * NumberArrayLengthDependency. If written in a sentence, the dependency reads like this:
00193    * The number of entry's in the "Amount in Buckets" array is dependent upon the "Number Of Buckets" parameter.
00194    *
00195    * Note how this time the parent list of the dependent and dependee are not My_deplist. They are the actual list
00196    * that the parameters a located in.
00197    */
00198   Teuchos::RCP<Optika::NumberArrayLengthDependency> arrayLengthDep = Teuchos::RCP<Optika::NumberArrayLengthDependency>(
00199     new Optika::NumberArrayLengthDependency(
00200   "Number Of Buckets", 
00201   Teuchos::sublist(My_deplist,"Water"),
00202   "Amount in Buckets", 
00203   Teuchos::sublist(My_deplist,"Water")));
00204 
00205   /*
00206    * Then add the dependency to the dependency sheet.
00207    */
00208   depSheet1->addDependency(arrayLengthDep);
00209 
00210   /*
00211    * Here we call the GUI. Before the user is able to input anything into the GUI, all dependencies are evaulated.
00212    * That way, any default dependee values will be expressed properly on their dependents.
00213    */
00214   Optika::getInput(My_deplist, depSheet1);
00215 
00216 
00217   /*
00218    * Printing out the Dep List that was used to construct the GUI.
00219    */
00220   Teuchos::RCP<Teuchos::FancyOStream> out = Teuchos::VerboseObjectBase::getDefaultOStream();
00221   std::cout << "Dep List: \n";
00222   Teuchos::writeParameterListToXmlOStream(*My_deplist, *out);
00223 
00224 
00225   /*
00226    * Final notes:
00227    *
00228    * Remember: It's always a good idea to make sure you're GUI works. Basic issues will not allow the GUI
00229    * to be even displayed to the user. So if your GUI can simply launch, that means you can feel pretty good
00230    * about the dependencies working the way they should. Still, you should make sure they do what you think
00231    * their doing.
00232    *
00233    * Remember: Dependents and Dependees don't have to have the same parent list. They just have to be located
00234    * some where in the "Root List" (or one of its sublists) of the dependency sheet.
00235    *
00236    * Remember: When making dependencies you must use the exact names of the the parameter and/or parameter lists
00237    * when specifying the dependent and the dependee. If you mispell the names, and there is no parameter and/or
00238    * parameter list by the name in the Root List (or one of it's sublists), the GUI won't even start up. 
00239    * It'll just throw and error. Worse, if you mispelled a name and there is a parameter or parameter list by 
00240    * that name in the root list, then your GUI will probably behave erratically.
00241    *
00242    * Remmeber: Different depenencies have different requirements. Be sure to check the documentation of the
00243    * dependency you're using to make sure you're getting it right. Otherwise you (or worse, your users) might
00244    * have some nasty problems down the road. Most of the time, if you try to preform a dependency incorrectly
00245    * your program will compile but the GUI will throw an error before it ever opens.
00246    *
00247    * Remember: All depenencies are evaluted before the user can ever interact with the GUI. Make sure that your
00248    * dependee's default values will result in desireable behavior.
00249    *
00250    * Remember: Arrays can't be dependees. If you would like this functionality please contact the author
00251    * of this package (Kurtis Nusbaum: klnusbaum@gmail.com), because he's thinking about including it in 
00252    * a future release.
00253    */
00254   return 0;
00255 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends