summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorjkinnebrew <jkinnebrew@ae88bc3d-4319-0410-8dbf-d08b4c9d3795>2009-12-29 22:36:29 +0000
committerjkinnebrew <jkinnebrew@ae88bc3d-4319-0410-8dbf-d08b4c9d3795>2009-12-29 22:36:29 +0000
commitaa28b017fc6276d6b41ddbdd7e09d195761dedf7 (patch)
tree566e7525eb7a0a6dcb30ea18153be847cdee4139
parentcd9ba4b205b47f9dfb5dfb08f6ab61f284545043 (diff)
downloadATCD-aa28b017fc6276d6b41ddbdd7e09d195761dedf7.tar.gz
Tue Dec 29 22:28:23 UTC 2009 John S. Kinnebrew <john.s.kinnebrew@vanderbilt.edu>
-rw-r--r--SA_POP/ChangeLog42
-rw-r--r--SA_POP/Planner.cpp14
-rw-r--r--SA_POP/SANet/SANet.cpp307
-rw-r--r--SA_POP/SANet/SANet.h153
-rw-r--r--SA_POP/SANet/SANet_Standalone.mpc8
-rw-r--r--SA_POP/SANet/SANet_Types.h19
-rw-r--r--SA_POP/SANet/SANet_UI.cpp524
-rw-r--r--SA_POP/SANet/SANode.cpp172
-rw-r--r--SA_POP/SANet/SANode.h69
-rw-r--r--SA_POP/SA_POP_Types.h18
-rw-r--r--SA_POP/Standalone/SAPOP_Demo.mpc15
-rw-r--r--SA_POP/Standalone/SA_POP_Demo.cpp102
-rw-r--r--SA_POP/Standalone/UserInput.cpp33
-rw-r--r--SA_POP/Standalone/UserInput.h42
-rw-r--r--SA_POP/UserInput/InputCL.cpp152
-rw-r--r--SA_POP/UserInput/InputCL.h166
-rw-r--r--SA_POP/UserInput/Question.cpp124
-rw-r--r--SA_POP/UserInput/Question.h172
18 files changed, 1683 insertions, 449 deletions
diff --git a/SA_POP/ChangeLog b/SA_POP/ChangeLog
index 8803fed21b2..97d4655fee6 100644
--- a/SA_POP/ChangeLog
+++ b/SA_POP/ChangeLog
@@ -1,3 +1,40 @@
+Tue Dec 29 22:28:23 UTC 2009 John S. Kinnebrew <john.s.kinnebrew@vanderbilt.edu>
+
+ * UserInput:
+ * UserInput/InputCL.h:
+ * UserInput/InputCL.cpp:
+ * UserInput/Question.h:
+ * UserInput/Question.cpp:
+
+ Added reusable text user interface.
+
+
+ * Standalone/SAPOP_Demo.mpc:
+ * Standalone/SA_POP_Demo.cpp:
+
+ Updated SA-POP Standalone to use new UI.
+
+
+ * Standalone/UserInput.h:
+ * Standalone/UserInput.cpp:
+
+ Removed these old UI files.
+
+
+ * Planner.cpp:
+ * SA_POP_Types.h:
+ * SANet/SANet.h:
+ * SANet/SANet.cpp:
+ * SANet/SANet_Standalone.mpc:
+ * SANet/SANet_Types.h:
+ * SANet/SANet_UI.cpp:
+ * SANet/SANode.h:
+ * SANet/SANode.cpp:
+
+ Added SANet cloning (deep copy by copy constructor).
+ Also cleaned up some more of the SANet code.
+
+
Fri Dec 18 20:28:36 UTC 2009 John S. Kinnebrew <john.s.kinnebrew@vanderbilt.edu>
* SA_POP_Types.h:
@@ -22,8 +59,8 @@ Fri Dec 18 01:00:33 UTC 2009 John S. Kinnebrew <john.s.kinnebrew@vanderbilt.ed
* SA_Builder.h:
* SA_Builder.cpp:
- Updated initialization of SA_Builder so overridden init()
- method will work correctly.
+ Updated initialization of SA_Builder so overriding init()
+ method will work correctly in derived classes.
* SAPOP_Exp_EU.mwc:
@@ -42,7 +79,6 @@ Fri Dec 18 01:00:33 UTC 2009 John S. Kinnebrew <john.s.kinnebrew@vanderbilt.ed
Added EU performance experiment skeleton.
-
* experiments/EU_Test:
* experiments/EU_Test/EU_Test.mpc:
* experiments/EU_Test/EU_Test.cpp:
diff --git a/SA_POP/Planner.cpp b/SA_POP/Planner.cpp
index 1862d015a70..89c3c1709a3 100644
--- a/SA_POP/Planner.cpp
+++ b/SA_POP/Planner.cpp
@@ -525,9 +525,6 @@ double Planner::calculate_plan_utility(size_t sa_max_steps)
this->sanet_->set_task_state(this->working_plan_->get_task_from_inst((*it).second), true);
this->sanet_->set_cond_state((*it).cond.id, true);
-// this->sanet_->note_causal_link(*it);
-
-
std::cout<<(*it).cond.id<<" cond, "<<(*it).first<<" first, "<<(*it).second<<" second"<<std::endl;
@@ -540,15 +537,18 @@ double Planner::calculate_plan_utility(size_t sa_max_steps)
this->sanet_->set_cond_state(it->first, true);
}
-// sanet_->restrict_prop_to_clinks(true);
sanet_->update(sa_max_steps);
-// sanet_->restrict_prop_to_clinks(false);
double conj_utils = 0;
for(GoalMap::iterator it = goals.begin(); it != goals.end(); it++){
std::cout<<it->second<<std::endl;
- std::cout<<this->sanet_->get_cond_future_val(it->first, this->sanet_->get_step())<<std::endl;
- conj_utils+=(it->second * this->sanet_->get_cond_future_val(it->first, this->sanet_->get_step()));
+ if (it->second >= 0.0) {
+ std::cout<<this->sanet_->get_cond_future_val(it->first, true)<<std::endl;
+ conj_utils+=(it->second * this->sanet_->get_cond_future_val(it->first, true));
+ } else {
+ std::cout<<this->sanet_->get_cond_future_val(it->first, false)<<std::endl;
+ conj_utils+=(it->second * this->sanet_->get_cond_future_val(it->first, false));
+ }
}
std::cout<<"Plan utility: "<<conj_utils<<std::endl;
diff --git a/SA_POP/SANet/SANet.cpp b/SA_POP/SANet/SANet.cpp
index 07cabb4066f..93883aaad50 100644
--- a/SA_POP/SANet/SANet.cpp
+++ b/SA_POP/SANet/SANet.cpp
@@ -17,16 +17,14 @@
#include "SANet.h"
#include "SANode.h"
#include "SANet_Exceptions.h"
-#include "SA_POP_Types.h"
using namespace SANet;
SANet::Network::Network (void)
: step_ (0)
-//, restrict_prop_to_clinks_(false)
{
- // Clear maps & sets.
+ // All map/set member variables initially empty.
this->task_nodes_.clear ();
this->cond_nodes_.clear ();
this->precond_links_.clear ();
@@ -36,14 +34,104 @@ SANet::Network::Network (void)
this->disabled_tasks_.clear ();
this->active_conds_.clear ();
this->disabled_conds_.clear ();
-// this->causal_links_by_first_.clear ();
-// this->causal_links_by_cond_.clear ();
-// this->causal_links_by_second_.clear ();
};
-int SANet::Network::get_step(){
- return step_;
-}
+
+// Copy constructor. Performs initialization by making a deep copy
+// of the provided network (including allocation of new nodes with
+// state copied from nodes in provided network and creation of
+// corresponding links between them).
+SANet::Network::Network (const Network &s)
+: step_ (s.step_)
+{
+ // Member variables that include node pointers are initially empty.
+ this->task_nodes_.clear ();
+ this->cond_nodes_.clear ();
+
+ // Member variables that include links are initially empty (will be populated during link creation).
+ this->precond_links_.clear ();
+ this->effect_links_.clear ();
+
+ // Copy active/disabled node (ID) sets (no node pointers and no links).
+ this->active_tasks_ = s.active_tasks_;
+ this->disabled_tasks_ = s.disabled_tasks_;
+ this->active_conds_ = s.active_conds_;
+ this->disabled_conds_ = s.disabled_conds_;
+
+ // Copy goals (no node pointers and no links).
+ this->goals_ = s.goals_;
+
+ // Create new nodes corresponding to those in s, adding each to appropriate node (ID to pointer) map.
+ for (TaskNodeMap::const_iterator node_iter = s.task_nodes_.begin ();
+ node_iter != s.task_nodes_.end (); node_iter++)
+ {
+ SANet::TaskNode *new_node = new SANet::TaskNode (*(node_iter->second));
+ this->task_nodes_.insert (std::make_pair (node_iter->first, new_node));
+ }
+ for (CondNodeMap::const_iterator node_iter = s.cond_nodes_.begin ();
+ node_iter != s.cond_nodes_.end (); node_iter++)
+ {
+ SANet::CondNode *new_node = new SANet::CondNode (*(node_iter->second));
+ this->cond_nodes_.insert (std::make_pair (node_iter->first, new_node));
+ }
+
+ // Create precondition links corresponding to all those in s
+ // (using pointers to new nodes instead of the original nodes in s).
+ for (PrecondLinkPortMap::const_iterator link_iter = s.precond_links_.begin ();
+ link_iter != s.precond_links_.end (); link_iter++)
+ {
+ PrecondLink link = link_iter->first;
+ PortID port = link_iter->second;
+
+ // Get pointer to task node in original network.
+ TaskNodeMap::const_iterator orig_task_iter = s.task_nodes_.find (link.second);
+ if (orig_task_iter == s.task_nodes_.end ())
+ throw UnknownNode ();
+ TaskNode *orig_task = orig_task_iter->second;
+
+ // Get precondition link conditional probabilities.
+ ConditionalProb prob = orig_task->get_precond_prob (link.first);
+
+ // Add precondition link.
+ this->add_precond_link (link.first, link.second, prob.true_prob, prob.false_prob, port);
+ }
+
+ // Create effect links corresponding to all those in s
+ // (using pointers to new nodes instead of the original nodes in s).
+ for (EffectLinkPortMap::const_iterator link_iter = s.effect_links_.begin ();
+ link_iter != s.effect_links_.end (); link_iter++)
+ {
+ EffectLink link = link_iter->first;
+ PortID port = link_iter->second;
+
+ // Get pointer to task node.
+ TaskNodeMap::const_iterator orig_task_iter = s.task_nodes_.find (link.first);
+ if (orig_task_iter == s.task_nodes_.end ())
+ throw UnknownNode ();
+ TaskNode *orig_task = orig_task_iter->second;
+
+ // Get effect link probability.
+ Probability prob = orig_task->get_effect_prob (link.second);
+
+ // Add effect link.
+ this->add_effect_link (link.first, link.second, prob, port);
+ }
+
+// Network data members
+ // STRUCTURE VARIABLES.
+// TaskNodeMap task_nodes_;
+// CondNodeMap cond_nodes_;
+// PrecondLinkPortMap precond_links_;
+// EffectLinkPortMap effect_links_;
+ // STATE VARIABLES.
+// TaskIDSet active_tasks_;
+// TaskIDSet disabled_tasks_;
+// CondIDSet active_conds_;
+// CondIDSet disabled_conds_;
+// GoalMap goals_;
+// int step_;
+};
+
SANet::Network::~Network ()
{
@@ -62,10 +150,6 @@ SANet::Network::~Network ()
}
};
-//void SANet::Network::restrict_prop_to_clinks(bool val){
-// restrict_prop_to_clinks_ = val;
-//};
-
void SANet::Network::add_task (TaskID ID, std::string name, MultFactor atten_factor,
TaskCost cost, Probability prior_prob)
{
@@ -104,40 +188,6 @@ void SANet::Network::reset_step(){
}
-/*
-void SANet::Network::note_causal_link(SA_POP::CausalLink clink){
- causal_links_by_first_.insert(std::pair<TaskID, SA_POP::CausalLink> (clink.first, clink));
- causal_links_by_cond_.insert(std::pair<CondID, SA_POP::CausalLink> (clink.cond.id, clink));
- causal_links_by_second_.insert(std::pair<TaskID, SA_POP::CausalLink> (clink.second, clink));
-}
-
-bool SANet::Network::is_clink_first_to_cond_by_first(TaskID task, CondID cond){
-
- for(std::multimap<SANet::TaskID, SA_POP::CausalLink>::iterator it = causal_links_by_first_.lower_bound(task);
- it != causal_links_by_first_.upper_bound(task); it++){
- SA_POP::CausalLink clink = it->second;
- if(clink.cond.id == cond){
- return true;
- }
- }
-
- return false;
-}
-
-bool SANet::Network::is_clink_first_to_cond_by_cond(CondID cond, TaskID task){
- for(std::multimap<SANet::CondID, SA_POP::CausalLink>::iterator it = causal_links_by_cond_.lower_bound(task);
- it != causal_links_by_cond_.upper_bound(cond); it++){
- SA_POP::CausalLink clink = it->second;
-
- if(clink.first == task){
- return true;
- }
- }
-
- return false;
-}
-*/
-
Probability SANet::Network::get_prior(TaskID ID)
{
TaskNodeMap::iterator task_iter = task_nodes_.find (ID);
@@ -536,13 +586,24 @@ Probability SANet::Network::get_cond_val (CondID cond_id)
return iter->second->get_init_prob ();
};
-Probability SANet::Network::get_cond_future_val(CondID cond_id, int step){
+// Get a condition's future probability for a given value.
+// (NOTE: Future probability is based on whatever spreading
+// activation has already been executed.)
+
+//****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****
+// (WARNING: Condition node must have been active for all
+// spreading activation or exception will be thrown.)
+//****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****
+
+Probability SANet::Network::get_cond_future_val(CondID cond_id, bool value)
+{
CondNodeMap::iterator iter = this->cond_nodes_.find(cond_id);
if(iter == this->cond_nodes_.end())
- throw "SANet::Network::get_cond_val (): Unknown condition node.";
- return iter->second->get_prob (step).probability;
+ throw "SANet::Network::get_cond_future_val (): Unknown condition node.";
+ return (iter->second->get_prob (this->step_, value)).probability;
}
+
// Get all goals.
const GoalMap& SANet::Network::get_goals (void)
{
@@ -665,12 +726,21 @@ CondSet SANet::Network::get_effects (TaskID task_id)
return effects;
};
+
+
+// ****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP
+// Ankit's function get_duration() needs to be removed, once we ensure any
+// scheduling code relying on it has been changed.
+
// Get the duration of a task.
TimeValue SANet::Network::get_duration (TaskID task_id)
{
TaskNode *temp = this->task_nodes_.find(task_id)->second;
return NULL_TIME;
}
+// ****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP
+
+
// Get all tasks that satisfy a condition.
TaskSet SANet::Network::get_satisfying_tasks (Condition cond)
@@ -739,98 +809,89 @@ LinkPorts SANet::Network::get_clink_ports (TaskID task1_id, CondID cond_id,
// Set Task State.
void SANet::Network::set_task_state(TaskID task_ID, bool state)
{
-
- task_nodes_.find(task_ID)->second->set_activity(state);
-
- if(state)
- {
- //insetr into active, remove from disabled
- this->active_tasks_.insert(task_ID);
-
- this->disabled_tasks_.erase(task_ID);
-
- }
- else
- {
- //remove from active, insert into disabled
-
- this->active_tasks_.erase(task_ID);
-
- this->disabled_tasks_.insert(task_ID);
- }
+ // Get pointer to node from ID.
+ SANet::TaskNodeMap::iterator task_iter = this->task_nodes_.find(task_ID);
+ if (task_iter == this->task_nodes_.end ())
+ throw UnknownNode ();
+
+ // Use node pointer to set activity state.
+ task_iter->second->set_activity(state);
+
+ if(state) {
+ // Insert into active task set & remove from disabled task set.
+ this->active_tasks_.insert(task_ID);
+ this->disabled_tasks_.erase(task_ID);
+ } else {
+ // Remove from active task set & insert into disabled task set.
+ this->active_tasks_.erase(task_ID);
+ this->disabled_tasks_.insert(task_ID);
+ }
};
// Set Cond State.
void SANet::Network::set_cond_state(CondID cond_ID, bool state)
{
- cond_nodes_.find(cond_ID)->second->set_activity(state);
- if(state)
- {
- //insetr into active, remove from disabled
- this->active_conds_.insert(cond_ID);
-
-
- this->disabled_conds_.erase(cond_ID);
-
- }
- else
- {
- //remove from active, insert into disabled
+ // Get pointer to node from ID.
+ SANet::CondNodeMap::iterator cond_iter = this->cond_nodes_.find(cond_ID);
+ if (cond_iter == this->cond_nodes_.end ())
+ throw UnknownNode ();
+
+ // Use node pointer to set activity state.
+ cond_iter->second->set_activity(state);
- this->active_conds_.erase(cond_ID);
+ if(state) {
+ // Insert into active condition set & remove from disabled condition set.
+ this->active_conds_.insert(cond_ID);
+ this->disabled_conds_.erase(cond_ID);
- this->disabled_conds_.insert(cond_ID);
- }
+ } else {
+ // Remove from active condition set & insert into disabled condition set.
+ this->active_conds_.erase(cond_ID);
+ this->disabled_conds_.insert(cond_ID);
+ }
};
// Set All nodes to State.
void SANet::Network::set_nodes_state(bool state)
{
- if(state)
+ if(state) {
+ // For all tasks, activate, insert into active set, & remove from disabled set.
+ for (TaskNodeMap::iterator node_iter = task_nodes_.begin ();
+ node_iter != task_nodes_.end (); node_iter++)
{
+ node_iter->second->set_activity(state);
+ this->active_tasks_.insert(node_iter->first);
+ this->disabled_tasks_.erase(node_iter->first);
+ }
- //insetr all tasks into active, remove from disabled
- for (TaskNodeMap::iterator node_iter = task_nodes_.begin ();
- node_iter != task_nodes_.end (); node_iter++)
- {
- node_iter->second->set_activity(state);
- this->active_tasks_.insert(node_iter->first);
-
- this->disabled_tasks_.erase(node_iter->first);
- }
-
- for (CondNodeMap::iterator node_iter = cond_nodes_.begin ();
- node_iter != cond_nodes_.end (); node_iter++)
- {
- node_iter->second->set_activity(state);
- this->active_conds_.insert(node_iter->first);
-
- this->disabled_conds_.erase(node_iter->first);
- }
+ // For all conditions, activate, insert into active set, & remove from disabled set.
+ for (CondNodeMap::iterator node_iter = cond_nodes_.begin ();
+ node_iter != cond_nodes_.end (); node_iter++)
+ {
+ node_iter->second->set_activity(state);
+ this->active_conds_.insert(node_iter->first);
+ this->disabled_conds_.erase(node_iter->first);
}
- else
+ } else {
+ // For all tasks, deactivate, remove from active set, & insert into disabled set.
+ for (TaskNodeMap::iterator node_iter = task_nodes_.begin ();
+ node_iter != task_nodes_.end (); node_iter++)
{
- //remove from active, insert into disabled
-
- for (TaskNodeMap::iterator node_iter = task_nodes_.begin ();
- node_iter != task_nodes_.end (); node_iter++)
- {
- node_iter->second->set_activity(state);
- this->active_tasks_.erase(node_iter->first);
-
- this->disabled_tasks_.insert(node_iter->first);
- }
-
- for (CondNodeMap::iterator node_iter = cond_nodes_.begin ();
- node_iter != cond_nodes_.end (); node_iter++)
- {
- node_iter->second->set_activity(state);
- this->active_conds_.erase(node_iter->first);
+ node_iter->second->set_activity(state);
+ this->active_tasks_.erase(node_iter->first);
+ this->disabled_tasks_.insert(node_iter->first);
+ }
- this->disabled_conds_.insert(node_iter->first);
- }
+ // For all conditions, deactivate, remove from active set, & insert into disabled set.
+ for (CondNodeMap::iterator node_iter = cond_nodes_.begin ();
+ node_iter != cond_nodes_.end (); node_iter++)
+ {
+ node_iter->second->set_activity(state);
+ this->active_conds_.erase(node_iter->first);
+ this->disabled_conds_.insert(node_iter->first);
}
+ }
}; \ No newline at end of file
diff --git a/SA_POP/SANet/SANet.h b/SA_POP/SANet/SANet.h
index ef49ed94473..b50318b17d5 100644
--- a/SA_POP/SANet/SANet.h
+++ b/SA_POP/SANet/SANet.h
@@ -17,12 +17,16 @@
#include <iostream>
#include <map>
#include <set>
-#include <stdexcept>
#include "SANet_Types.h"
#include "SANode.h"
-#include "SA_POP_Types.h"
namespace SANet {
+ /// Set of task node IDs.
+ typedef std::set<TaskID> TaskIDSet;
+
+ /// Set of condition node IDs.
+ typedef std::set<CondID> CondIDSet;
+
/// Map from task node ID to pointer.
typedef std::map<TaskID, TaskNode *> TaskNodeMap;
@@ -45,13 +49,22 @@ namespace SANet {
/// Constructor.
Network (void);
+ /// Copy constructor. Performs initialization by making a deep copy
+ /// of the provided network (including allocation of new nodes with
+ /// state copied from nodes in provided network and creation of
+ /// corresponding links between them).
+ /**
+ * @param s Network to copy.
+ */
+ Network (const Network &s);
+
/// Destructor.
virtual ~Network ();
// ************************************************************************
- // Network creations methods.
+ // Network creation methods.
// ************************************************************************
/// Add a new task node to the network.
@@ -81,9 +94,9 @@ namespace SANet {
*
* @param false_prob Initial probability that value is false.
*
- * @param cond_kind The type of condition
+ * @param cond_kind The type of condition.
*
- * @param goal_util Initial utility (positive for goals, zero otherwise).
+ * @param goal_util Initial utility (positive for TRUE goals, negative for FALSE goals, and zero for non-goals).
*/
virtual void add_cond (CondID ID, std::string name,
MultFactor atten_factor, Probability true_prob, Probability false_prob,
@@ -115,35 +128,12 @@ namespace SANet {
*
* @param weight Link weight (probability task sets condition to
* true, or negative of the probability task sets condition to false).
- *
- * @param port_ID ID of port (on task) associated with this condition
+ * * @param port_ID ID of port (on task) associated with this condition
* (used for data nodes).
*/
virtual void add_effect_link (TaskID task_ID, CondID cond_ID,
LinkWeight weight, PortID port_ID = "");
- /// Set the state of a task node.
- /**
- * @param task_ID Task node ID.
- *
- * @param state New state (false for inactive, and true for active);
- */
- virtual void set_task_state(TaskID task_ID, bool state);
-
- /// Set the state of a condition node.
- /**
- * @param cond_ID Condition node ID.
- *
- * @param state New state (false for inactive, and true for active);
- */
- virtual void set_cond_state(CondID cond_ID, bool state);
-
- /// Set state of all nodes.
- /**
- * @param state New state (false for inactive, and true for active);
- */
- virtual void set_nodes_state(bool state);
-
@@ -163,12 +153,14 @@ namespace SANet {
/// Print Graphviz network representation to stream.
/**
* @param strm Output stream on which to print network representation.
+ *
* @param graphmap The color mapping being used.
+ *
* @param defaultColor The default color if it's not in the mapping.
*/
- virtual void print_graphviz (std::basic_ostream<char, std::char_traits<char> >& strm, std::map<std::string, std::string>& graphmap, std::string defaultColor = "grey");
-
-
+ virtual void print_graphviz (std::basic_ostream<char,
+ std::char_traits<char> >& strm, std::map<std::string, std::string>& graphmap,
+ std::string defaultColor = "grey");
/// Print XML network representation to stream.
/**
@@ -226,7 +218,7 @@ namespace SANet {
*
* @param prior New prior probability;
*/
- virtual void update_prior(TaskID task_ID, Probability prior);
+ virtual void update_prior (TaskID task_ID, Probability prior);
/// Update a task to condition link.
/**
@@ -240,8 +232,30 @@ namespace SANet {
* @param port_ID ID of port (on task) associated with this condition
* (used for data nodes).
*/
- virtual void update_effect_link(TaskID task_ID, CondID cond_ID,
- LinkWeight weight, PortID port_ID= "");
+ virtual void update_effect_link (TaskID task_ID, CondID cond_ID,
+ LinkWeight weight, PortID port_ID= "");
+
+ /// Set the state of a task node.
+ /**
+ * @param task_ID Task node ID.
+ *
+ * @param state New state (false for inactive, and true for active);
+ */
+ virtual void set_task_state(TaskID task_ID, bool state);
+
+ /// Set the state of a condition node.
+ /**
+ * @param cond_ID Condition node ID.
+ *
+ * @param state New state (false for inactive, and true for active);
+ */
+ virtual void set_cond_state(CondID cond_ID, bool state);
+
+ /// Set state of all nodes.
+ /**
+ * @param state New state (false for inactive, and true for active);
+ */
+ virtual void set_nodes_state(bool state);
@@ -283,6 +297,20 @@ namespace SANet {
*/
virtual Probability get_cond_val (CondID cond_id);
+ /// Get a condition's future probability for a given value.
+ /// (NOTE: Future probability is based on whatever spreading
+ /// activiation has already been executed.)
+ /// (WARNING: Condition node must have been active for all
+ /// spreading activation or exception will be thrown.)
+ /**
+ * @param cond_id Condition ID.
+ *
+ * @param value Value for which to get condition future probability.
+ *
+ * @return Future task expected utility.
+ */
+ Probability get_cond_future_val(CondID cond_id, bool value);
+
/// Get all goals.
/**
* @return Set of condition ids and associated utilities.
@@ -298,6 +326,8 @@ namespace SANet {
virtual Utility get_task_current_eu (TaskID task_id);
/// Get a task's future expected utility.
+ /// (NOTE: Future probability is based on whatever spreading
+ /// activiation has already been executed).
/**
* @param task_id The task id.
*
@@ -363,7 +393,7 @@ namespace SANet {
/// Get the prior probability for a task node in the network.
/**
- * @param ID Node ID.
+ * @param ID ID of task node.
*
* @returns Prior probability of the task.
*/
@@ -373,29 +403,27 @@ namespace SANet {
/**
* @param task_ID Task ID.
*
- * @param cond_ID Cond ID.
+ * @param cond_ID Condition ID.
*
* @returns Weight of the effect link.
*/
virtual LinkWeight get_link(TaskID task_ID, CondID cond_ID);
+
+ // ****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP
+ // Ankit's function get_duration() needs to be removed, once we ensure any
+ // scheduling code relying on it has been changed.
+ // ****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP
+
/// Get the duration of a task
/**
- * @param task_id ID of the Task
+ * @param task_id Task ID.
*
- * @return duration of the task
+ * @return Duration of the task.
*/
virtual TimeValue get_duration (TaskID task_id);
- Probability get_cond_future_val(int step, CondID cond_id);
-
- int get_step();
-
-// void note_causal_link(SA_POP::CausalLink clink);
-
-// void restrict_prop_to_clinks(bool val);
-
protected:
// ************************************************************************
@@ -420,17 +448,17 @@ namespace SANet {
// State variables.
// ************************************************************************
- //Set of Active Task Nodes
- std::set<SANet::TaskID> active_tasks_;
+ /// Set of active task nodes (by ID).
+ TaskIDSet active_tasks_;
- //Set of Disabled Task Nodes
- std::set<SANet::TaskID> disabled_tasks_;
+ /// Set of disabled task nodes (by ID).
+ TaskIDSet disabled_tasks_;
- //Set of Active Condition Nodes
- std::set<SANet::CondID> active_conds_;
+ /// Set of active condition nodes (by ID).
+ CondIDSet active_conds_;
- //Set of Active Task Nodes
- std::set<SANet::CondID> disabled_conds_;
+ /// Set of disabled condition nodes (by ID).
+ CondIDSet disabled_conds_;
/// Goals.
GoalMap goals_;
@@ -439,26 +467,11 @@ namespace SANet {
int step_;
-
-// bool restrict_prop_to_clinks_;
-
-
-// std::multimap<TaskID, SA_POP::CausalLink> causal_links_by_first_;
-// std::multimap<CondID, SA_POP::CausalLink> causal_links_by_cond_;
-// std::multimap<TaskID, SA_POP::CausalLink> causal_links_by_second_;
-
-
-
// ************************************************************************
// State helper methods.
// ************************************************************************
void reset_step();
-
- //bool is_clink_first_to_cond_by_first(TaskID task, CondID cond);
- //bool is_clink_first_to_cond_by_cond (CondID cond, TaskID task);
- //bool is_clink_cond_to_second_by_second(TaskID task, CondID cond);
- //bool is_clink_cond_to_second_by_cond(CondID cond, TaskiD second);
};
};
diff --git a/SA_POP/SANet/SANet_Standalone.mpc b/SA_POP/SANet/SANet_Standalone.mpc
index d49da025fcc..0f6a4c4b165 100644
--- a/SA_POP/SANet/SANet_Standalone.mpc
+++ b/SA_POP/SANet/SANet_Standalone.mpc
@@ -1,7 +1,8 @@
project(SANet_Demo) : xerces, aceexe, sapop_xml {
exename = SANet_Demo
- includes += $(SAPOP_ROOT)
+ includes += $(SAPOP_ROOT) \
+ $(SAPOP_ROOT)/UserInput
macros = SANET_STANDALONE
@@ -15,6 +16,9 @@ project(SANet_Demo) : xerces, aceexe, sapop_xml {
SANet_XML_Typedefs.h
SANetFileIn.h
+
+ $(SAPOP_ROOT)/UserInput/InputCL.h
+ $(SAPOP_ROOT)/UserInput/Question.h
}
@@ -29,6 +33,8 @@ project(SANet_Demo) : xerces, aceexe, sapop_xml {
SANet_XML_Typedefs.cpp
SANetFileIn.cpp
XML_SANet.cpp
+
+ $(SAPOP_ROOT)/UserInput/InputCL.cpp
}
Documentation_Files {
diff --git a/SA_POP/SANet/SANet_Types.h b/SA_POP/SANet/SANet_Types.h
index fa52d12647d..5b4483b516f 100644
--- a/SA_POP/SANet/SANet_Types.h
+++ b/SA_POP/SANet/SANet_Types.h
@@ -68,6 +68,9 @@ namespace SANet {
/// Type of a probability.
typedef SA_POP::Probability Probability;
+ /// Type of a conditional probability.
+ typedef SA_POP::ConditionalProb ConditionalProb;
+
/// Type of a (precondition or effect) link weight.
typedef SA_POP::LinkWeight LinkWeight;
@@ -248,6 +251,22 @@ namespace SANet {
/// Type of a probability.
typedef EUCalc Probability;
+ /// Type of a conditional probability.
+ struct ConditionalProb {
+ // Probability when conditioned variable is true.
+ Probability true_prob;
+ // Probability when conditioned variable is false.
+ Probability false_prob;
+ bool operator== (const ConditionalProb &s) const { return this->true_prob == s.true_prob && this->false_prob == s.false_prob; };
+ bool operator!= (const ConditionalProb &s) const { return !(*this == s); };
+ bool operator< (const ConditionalProb &s) const
+ {
+ if (this->true_prob == s.true_prob)
+ return this->false_prob < s.false_prob;
+ return this->true_prob < s.true_prob;
+ };
+ };
+
/// Type of a (precondition or effect) link weight.
typedef EUCalc LinkWeight;
diff --git a/SA_POP/SANet/SANet_UI.cpp b/SA_POP/SANet/SANet_UI.cpp
index aeddd1edb6d..ad18f08cab1 100644
--- a/SA_POP/SANet/SANet_UI.cpp
+++ b/SA_POP/SANet/SANet_UI.cpp
@@ -20,6 +20,19 @@
#include <string>
#include "SANet.h"
#include "SANetFileIn.h"
+#include "InputCL.h"
+
+
+namespace SANet {
+ namespace Default {
+ const size_t SA_MAX_STEPS = 1000;
+ }; /* SANet::Default namespace */
+}; /* SANet namespace */
+
+// Forward declaration of testing functions.
+int test_clone (std::string filename);
+int test_user_interface (void);
+int test_net_gen (void);
using namespace SANet;
@@ -33,46 +46,402 @@ using namespace SANet;
*/
int main (int argc, char *argv[])
{
- std::cout << "Spreading Activation Network User Interface" << std::endl;
+ std::cout << "Spreading Activation Network User Interface" << std::endl << std::endl;
+
+ // To run a test, uncomment appropriate test function.
+// return test_clone ("simple.san.xml");
+// return test_net_gen ();
+// return test_user_interface ();
+
+ UserInterface::InputCL user_input;
// Get filename from user.
- std::cout << "Network file: ";
std::string filename = "";
- std::cin >> filename;
+ UserInterface::Question file_ques ("Spreading activation network file:");
+ if (user_input.ask (file_ques))
+ filename = file_ques.get_answer ();
+
+ // Get flag for whether to output network configurations to files.
+ bool output_to_file = false;
// Build network.
SANetFileIn in;
SANet::Network *net = in.build_net (filename);
- // Print XML representation to output1.xml.
- std::ofstream out_file ("output1.xml");
- if (out_file == 0){
- std::string msg = "Unable to open output1.xml for writing";
- throw msg;
+ // Display initial configuration.
+ std::cout << "Initial network configuration:" << std::endl;
+ net->print (std::cout, true);
+
+ // Print XML representation to output_init.xml.
+ if (output_to_file) {
+ std::ofstream file_init ("output_init.xml");
+ if (file_init == 0){
+ std::string msg = "Unable to open output_init.xml for writing";
+ throw msg;
+ }
+ net->print_xml (file_init);
+ file_init.close ();
}
- net->print_xml (out_file);
- out_file.close ();
-/*
- net->add_cond (1111, "C1", 1, 1, 0, 0);
- net->add_cond (1112, "C2", 1, 1, 0, 0);
+ // Get max steps from user.
+ size_t max_steps = SANet::Default::SA_MAX_STEPS;
+ UserInterface::QuestionInt steps_ques("Max steps to run (10000 step limit): ", 0, 10000);
+ if (user_input.ask (steps_ques))
+ max_steps = steps_ques.get_answer_int ();
+
+
+ // Run spreading activation.
+ net->update (max_steps);
+
+ // Display final configuration.
+ std::cout << "Final network configuration:" << std::endl;
+ net->print (std::cout, true);
+
+ // Print XML representation to output_final.xml.
+ if (output_to_file) {
+ std::ofstream file_final ("output_final.xml");
+ if (file_final == 0){
+ std::string msg = "Unable to open output_final.xml for writing";
+ throw msg;
+ }
+ net->print_xml (file_final);
+ file_final.close ();
+ }
+
+ // Delete network.
+ delete net;
+
+ // Wait for user to end program.
+// UserInterface::Question end_ques ("Enter any character to end program:");
+// user_input.ask (end_ques);
+
+ return 0;
+};
+
+int test_clone (std::string filename, bool output_to_file = false)
+{
+ UserInterface::InputCL user_input;
+
+ // Build network.
+ SANetFileIn in;
+ SANet::Network *net = in.build_net (filename);
+
+ // Create initial network clone.
+ SANet::Network *net_dupe_init = new SANet::Network (*net);
+
+ // Display initial configurations.
+ std::cout << "Initial network configuration:" << std::endl;
+ net->print (std::cout, true);
+ std::cout << "Initial clone network configuration:" << std::endl;
+ net_dupe_init->print (std::cout, true);
+
+ // Print initial XML representation of networks.
+ if (output_to_file) {
+ // Print initial network XML representation.
+ std::ofstream file_init ("output_init.xml");
+ if (file_init == 0){
+ std::string msg = "Unable to open output_init.xml for writing";
+ throw msg;
+ }
+ net->print_xml (file_init);
+ file_init.close ();
+
+ // Print initial clone network XML representation.
+ std::ofstream file_dupe_init ("output_clone_init.xml");
+ if (file_dupe_init == 0){
+ std::string msg = "Unable to open output_clone_init.xml for writing";
+ throw msg;
+ }
+ net_dupe_init->print_xml (file_dupe_init);
+ file_dupe_init.close ();
+ }
+
+ // Get max steps from user.
+ size_t max_steps = SANet::Default::SA_MAX_STEPS;
+ UserInterface::QuestionInt steps_ques("Max steps to run (10000 step limit): ", 0, 10000);
+ if (user_input.ask (steps_ques))
+ max_steps = steps_ques.get_answer_int ();
+
+ // Run spreading activation on original network.
+ net->update (max_steps);
+
+ // Clone updated network.
+ SANet::Network *net_dupe_final = new SANet::Network (*net);
+
+ // Display final configurations.
+ std::cout << "Final network configuration (ORIGINAL net) after spreading activation:" << std::endl;
+ net->print (std::cout, true);
+ std::cout << "Network configuration (CLONE of INITIAL net with no spreading activation performed):" << std::endl;
+ net_dupe_init->print (std::cout, true);
+ std::cout << "Network configuration (CLONE of FINAL net after spreading activation):" << std::endl;
+ net_dupe_final->print (std::cout, true);
+
+ // Print final XML representation of networks.
+ if (output_to_file) {
+ // Print network XML representation.
+ std::ofstream file_final ("output_final.xml");
+ if (file_final == 0){
+ std::string msg = "Unable to open output_final.xml for writing";
+ throw msg;
+ }
+ net->print_xml (file_final);
+ file_final.close ();
+
+ // Print clone network XML representation.
+ std::ofstream file_dupe_final ("output_clone_final.xml");
+ if (file_dupe_final == 0){
+ std::string msg = "Unable to open output_clone_final.xml for writing";
+ throw msg;
+ }
+ net_dupe_init->print_xml (file_dupe_final);
+ file_dupe_final.close ();
+
+ // Print second (after SA) clone network XML representation.
+ std::ofstream file_dupe2_final ("output_clone2_final.xml");
+ if (file_dupe2_final == 0){
+ std::string msg = "Unable to open output_clone2_final.xml for writing";
+ throw msg;
+ }
+ net_dupe_final->print_xml (file_dupe2_final);
+ file_dupe2_final.close ();
+ }
+
+
+ // Run spreading activation on clones.
+ net_dupe_init->update (max_steps);
+ net_dupe_final->update (max_steps);
+
+ // Display final configurations.
+ std::cout << "Final network configuration (CLONE of INITIAL net) after spreading activation:" << std::endl;
+ net_dupe_init->print (std::cout, true);
+ std::cout << "Final network configuration (CLONE of FINAL net) after additional spreading activation:" << std::endl;
+ net_dupe_final->print (std::cout, true);
+
+
+ // Delete networks.
+ delete net;
+ delete net_dupe_init;
+ delete net_dupe_final;
+
+ // Wait for user to end program.
+ UserInterface::Question end_ques ("Enter any character to end program:");
+ user_input.ask (end_ques);
+
+ return 0;
+};
+
+
+
+namespace UserInterface {
+ namespace Testing {
+ /// Type of an example enumerated type for user input.
+ enum RunKind {CONTINUE, STOP, EXIT, INVALID};
+ }; /* UserInterface::Testing namespace */
+}; /* UserInterface namespace */
+
+
+int test_user_interface (void)
+{
+ std::string answer = "999999";
+ int answer_int = 999999;
+ UserInterface::Testing::RunKind answer_val = UserInterface::Testing::INVALID;
+ std::string answer_val_str = "InVsTr";
+ bool answer_bool = false;
+
+ UserInterface::InputCL user_input;
+
+ UserInterface::Question ques ("Testing display info.");
+
+ user_input.info (ques);
+
+ ques.set_prompt ("Testing prompt (enter anything):");
+ user_input.ask (ques);
+ std::cout << "Your answer was \"" << ques.get_answer () << "\"" << std::endl;
+
+ answer = "999999";
+ answer_int = 999999;
+ UserInterface::QuestionInt ques_int ("Enter an integer between -100 and 5000:", -100, 5000);
+
+ user_input.ask (ques_int);
+ answer = ques_int.get_answer ();
+ answer_int = ques_int.get_answer_int ();
+ std::cout << "Your answer was \"" << answer << "\" which equals " << answer_int << "." << std::endl;
+
+
+
+
+ std::cout << "QuestionChoice<int> case insensitive" << std::endl;
+ UserInterface::QuestionChoice<int> ques_choice_int ("Enter (O)ne, (T)wo, or (F)our:", -1);
+ ques_choice_int.add_mapping ("O", 1);
+ ques_choice_int.add_mapping ("One", 1);
+ ques_choice_int.add_mapping ("T", 2);
+ ques_choice_int.add_mapping ("Two", 2);
+ ques_choice_int.add_mapping ("F", 4);
+ ques_choice_int.add_mapping ("Four", 4);
+
+ answer = "InV";
+ answer_val_str = "InVsTr";
+ answer_int = -2;
+
+ user_input.ask (ques_choice_int);
+ answer = ques_choice_int.get_answer ();
+ answer_int = ques_choice_int.get_answer_val ();
+ switch (answer_int)
+ {
+ case 1:
+ answer_val_str = "1 value";
+ break;
+ case 2:
+ answer_val_str = "2 value";
+ break;
+ case 4:
+ answer_val_str = "4 value";
+ break;
+ case -1:
+ answer_val_str = "INVALID value";
+ break;
+ default:
+ answer_val_str = "Unknown answer value";
+ break;
+ }
+ std::cout << "Your answer was \"" << answer << "\" which equals " << answer_val_str << "." << std::endl;
+
+
+
+
+ std::cout << "QuestionChoice case insensitive" << std::endl;
+ UserInterface::QuestionChoice<UserInterface::Testing::RunKind> ques_choice ("Enter (C)ontinue, (S)top, or (E)xit:", UserInterface::Testing::INVALID);
+ ques_choice.add_mapping ("C", UserInterface::Testing::CONTINUE);
+ ques_choice.add_mapping ("Continue", UserInterface::Testing::CONTINUE);
+ ques_choice.add_mapping ("S", UserInterface::Testing::STOP);
+ ques_choice.add_mapping ("Stop", UserInterface::Testing::STOP);
+ ques_choice.add_mapping ("E", UserInterface::Testing::EXIT);
+ ques_choice.add_mapping ("Exit", UserInterface::Testing::EXIT);
+
+ answer = "InV";
+ answer_val_str = "InVsTr";
+ answer_val = UserInterface::Testing::INVALID;
+
+ user_input.ask (ques_choice);
+ answer = ques_choice.get_answer ();
+ answer_val = ques_choice.get_answer_val ();
+ switch (answer_val)
+ {
+ case UserInterface::Testing::CONTINUE:
+ answer_val_str = "CONTINUE value";
+ break;
+ case UserInterface::Testing::STOP:
+ answer_val_str = "STOP value";
+ break;
+ case UserInterface::Testing::EXIT:
+ answer_val_str = "EXIT value";
+ break;
+ case UserInterface::Testing::INVALID:
+ answer_val_str = "INVALID value";
+ break;
+ default:
+ answer_val_str = "Unknown answer value";
+ break;
+ }
+ std::cout << "Your answer was \"" << answer << "\" which equals " << answer_val_str << "." << std::endl;
+
+
+ std::cout << "QuestionChoice case sensitive" << std::endl;
+ UserInterface::QuestionChoice<UserInterface::Testing::RunKind> ques_choice_case ("Enter (C)ontinue, (S)top, or (E)xit:", UserInterface::Testing::INVALID, true);
+ ques_choice_case.add_mapping ("C", UserInterface::Testing::CONTINUE);
+ ques_choice_case.add_mapping ("Continue", UserInterface::Testing::CONTINUE);
+ ques_choice_case.add_mapping ("S", UserInterface::Testing::STOP);
+ ques_choice_case.add_mapping ("Stop", UserInterface::Testing::STOP);
+ ques_choice_case.add_mapping ("E", UserInterface::Testing::EXIT);
+ ques_choice_case.add_mapping ("Exit", UserInterface::Testing::EXIT);
+
+ answer = "InV";
+ answer_val_str = "InVsTr";
+ answer_val = UserInterface::Testing::INVALID;
+
+ user_input.ask (ques_choice_case);
+ answer = ques_choice_case.get_answer ();
+ answer_val = ques_choice_case.get_answer_val ();
+ switch (answer_val)
+ {
+ case UserInterface::Testing::CONTINUE:
+ answer_val_str = "CONTINUE value";
+ break;
+ case UserInterface::Testing::STOP:
+ answer_val_str = "STOP value";
+ break;
+ case UserInterface::Testing::EXIT:
+ answer_val_str = "EXIT value";
+ break;
+ case UserInterface::Testing::INVALID:
+ answer_val_str = "INVALID value";
+ break;
+ default:
+ answer_val_str = "Unknown answer value";
+ break;
+ }
+ std::cout << "Your answer was \"" << answer << "\" which equals " << answer_val_str << "." << std::endl;
+
+
+ std::cout << "QuestionBool" << std::endl;
+ UserInterface::QuestionBool ques_bool ("Enter (Y)es or (N)o:", false);
+
+ answer = "InV";
+ answer_val_str = "InVsTr";
+ answer_bool = true;
+
+ user_input.ask (ques_bool);
+ answer = ques_bool.get_answer ();
+ answer_bool = ques_bool.get_answer_val ();
+ switch (answer_bool)
+ {
+ case true:
+ answer_val_str = "TRUE value";
+ break;
+ case false:
+ answer_val_str = "FALSE value";
+ break;
+ default:
+ answer_val_str = "Unknown answer value";
+ break;
+ }
+ std::cout << "Your answer was \"" << answer << "\" which equals " << answer_val_str << "." << std::endl;
+
+
+ // Wait for user to end program.
+ UserInterface::Question end_ques ("Enter any character to end program:");
+ user_input.ask (end_ques);
+
+ return 0;
+};
+
+
+
+int test_net_gen (void)
+{
+ UserInterface::InputCL user_input;
+
+ // Build network.
+ SANet::Network *net = new SANet::Network ();
+
+ net->add_cond (1111, "C1", 1, 1, 0, 0, ENVIRON);
+ net->add_cond (1112, "C2", 1, 1, 0, 0, ENVIRON);
net->add_task (2221, "A1", 1, 0, 0.375);
- net->add_cond (1113, "C3", 1, 0, 1, 10);
- net->add_cond (1114, "C4", 1, 0, 1, 10);
+ net->add_cond (1113, "C3", 1, 0, 1, 10, ENVIRON);
+ net->add_cond (1114, "C4", 1, 0, 1, 10, ENVIRON);
net->add_precond_link (1111, 2221, 0.75, 0);
net->add_precond_link (1112, 2221, 0.5, 0.25);
net->add_effect_link (2221, 1113, 1);
net->add_effect_link (2221, 1114, 0.9);
-*/
/*
- net->add_cond (1110, "C0", 1, 1, 0, 0);
+ net->add_cond (1110, "C0", 1, 1, 0, 0, ENVIRON);
net->add_task (2221, "A1", 1, 0, 0.5);
net->add_task (2222, "A2", 1, 0, 0.5);
- net->add_cond (1111, "C1", 1, 0, 1, 0);
- net->add_cond (1112, "C2", 1, 0, 1, 0);
+ net->add_cond (1111, "C1", 1, 0, 1, 0, ENVIRON);
+ net->add_cond (1112, "C2", 1, 0, 1, 0, ENVIRON);
net->add_task (2223, "A3", 1, 1, 0.25);
- net->add_cond (1113, "C3", 1, 0, 1, 10);
+ net->add_cond (1113, "C3", 1, 0, 1, 10, ENVIRON);
net->add_precond_link (1110, 2221, 1, 0);
net->add_precond_link (1110, 2222, 1, 0);
net->add_effect_link (2221, 1111, 1);
@@ -83,115 +452,58 @@ int main (int argc, char *argv[])
*/
/*
- net->add_cond (1111, "C1", 1, 1, 0, 0);
- net->add_cond (1112, "C2", 1, 1, 0, 0);
+ net->add_cond (1111, "C1", 1, 1, 0, 0, ENVIRON);
+ net->add_cond (1112, "C2", 1, 1, 0, 0, ENVIRON);
net->add_task (2221, "A1", 1, 1, 0.5);
net->add_task (2222, "A2", 1, 3, 0.5);
- net->add_cond (1113, "C3", 1, 0, 1, 10);
+ net->add_cond (1113, "C3", 1, 0, 1, 10, ENVIRON);
net->add_precond_link (1111, 2221, 1, 0);
net->add_precond_link (1112, 2222, 1, 0);
net->add_effect_link (2221, 1113, 1);
net->add_effect_link (2222, 1113, -1);
*/
-/*
- net->print ();
-
- net->update (10);
- std::cout << std::endl;
+ // Display initial configuration.
+ std::cout << "Initial network configuration:" << std::endl;
net->print (std::cout, true);
-*/
-
-/*
- std::string filename = "";
- Parser::XML_Parser parser;
- Parser::XML_Object *obj;
- Parser::SA_Net_Builder builder;
- Network *net;
-
- // Get network file from user.
- std::cout << "Network file: ";
- std::cin >> filename;
-
- try {
- obj = parser.parse_file (filename);
- } catch (Parser::Invalid_File e) {
- std::cerr << "Invalid File exception occurred while opening network file." << std::endl;
- std::cerr << e.err_msg ();
- return -1;
- } catch (Parser::Duplicate_Param e) {
- std::cerr << "Duplicate Parameter exception occurred while parsing network file." << std::endl;
- std::cerr << e.err_msg ();
- return -1;
- } catch (Parser::Invalid_Character e) {
- std::cerr << "Invalid Character exception occurred while parsing network file." << std::endl;
- std::cerr << e.err_msg ();
- return -1;
- } catch (Parser::Invalid_Param_Name e) {
- std::cerr << "Invalid Parameter Name exception occurred while parsing network file." << std::endl;
- std::cerr << e.err_msg ();
- return -1;
- } catch (Parser::Invalid_Param_Type e) {
- std::cerr << "Invalid Parameter Type exception occurred while parsing network file." << std::endl;
- std::cerr << e.err_msg ();
- return -1;
- } catch (Parser::Invalid_Tag_Name e) {
- std::cerr << "Invalid Tag Name exception occurred while parsing network file." << std::endl;
- std::cerr << e.err_msg ();
- return -1;
- } catch (char *e) {
- std::cerr << "Exception occurred while parsing network file." << std::endl;
- std::cerr << e;
- return -1;
- } catch (...) {
- std::cerr << "Unknown exception occurred while parsing network file.";
- std::cerr << std::endl;
- return -1;
- }
- try {
- net = builder.build_net (obj);
- } catch (char *e) {
- std::cerr << "Exception occurred while building network." << std::endl;
- std::cerr << e;
- return -1;
- } catch (...) {
- std::cerr << "Unknown exception occurred while building network.";
- std::cerr << std::endl;
- return -1;
+ // Print XML representation to output_init.xml.
+ std::ofstream file_init ("output_init.xml");
+ if (file_init == 0){
+ std::string msg = "Unable to open output_init.xml for writing";
+ throw msg;
}
-*/
- std::cout << "Initial network configuration:" << std::endl;
- net->print ();
+ net->print_xml (file_init);
+ file_init.close ();
// Get max steps from user.
- std::cout << "Max steps to run: ";
- std::string max_steps_str = "";
- std::cin >> max_steps_str;
-
+ size_t max_steps = SANet::Default::SA_MAX_STEPS;
+ UserInterface::QuestionInt steps_ques("Max steps to run (10000 step limit): ", 0, 10000);
+ if (user_input.ask (steps_ques))
+ max_steps = steps_ques.get_answer_int ();
+
// Run spreading activation.
- net->update (atoi (max_steps_str.c_str ()));
+ net->update (max_steps);
+ // Display final configuration.
std::cout << "Final network configuration:" << std::endl;
net->print (std::cout, true);
- std::ofstream out2_file ("output2.xml");
- if (out2_file == 0){
- std::string msg = "Unable to open output2.xml for writing";
+ // Print XML representation to output_final.xml.
+ std::ofstream file_final ("output_final.xml");
+ if (file_final == 0){
+ std::string msg = "Unable to open output_final.xml for writing";
throw msg;
}
- net->print_xml (out2_file);
- out2_file.close ();
+ net->print_xml (file_final);
+ file_final.close ();
-// delete obj;
delete net;
-//****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP
- std::cout << "Enter any character to end program: ";
- char temp_;
- std::cin>>temp_;
-//****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP
+ // Wait for user to end program.
+ UserInterface::Question end_ques ("Enter any character to end program:");
+ user_input.ask (end_ques);
return 0;
-}
+};
diff --git a/SA_POP/SANet/SANode.cpp b/SA_POP/SANet/SANode.cpp
index 2a8838043a8..0eacee63dec 100644
--- a/SA_POP/SANet/SANode.cpp
+++ b/SA_POP/SANet/SANode.cpp
@@ -25,7 +25,7 @@ Node::Node (NodeID ID, std::string name, MultFactor atten_factor)
step_ (0),
prob_changed_ (false),
util_changed_ (false) ,
- active(true)
+ active_ (true)
{
// Initialize probability and utility info.
pos_util_.utility = 0;
@@ -44,6 +44,50 @@ Node::Node (NodeID ID, std::string name, MultFactor atten_factor)
post_links_.clear ();
};
+// Copy constructor. Performs initialization by making a deep copy
+// of the provided node (with the exception of network structural
+// information about other nodes).
+// (WARNING: Links, including their probability values and node
+// pointers, to & from this node are EMPTY in the newly created copy.)
+Node::Node (const Node &s)
+: ID_ (s.ID_),
+ active_ (s.active_),
+ name_ (s.name_),
+ atten_factor_ (s.atten_factor_),
+ step_ (s.step_),
+ prob_changed_ (s.prob_changed_),
+ util_changed_ (s.util_changed_)
+{
+ // Initialize probability and utility info.
+ this->pos_util_ = s.pos_util_;
+ this->neg_util_ = s.neg_util_;
+ this->true_prob_ = s.true_prob_;
+ this->false_prob_ = s.false_prob_;
+
+ // Initialize (EMPTY) pre- and post-node maps & links.
+ this->pre_nodes_.clear ();
+ this->pre_links_.clear ();
+ this->post_nodes_.clear ();
+ this->post_links_.clear ();
+
+// Node data members.
+// NodeID ID_;
+// bool active_;
+// std::string name_;
+// MultFactor atten_factor_;
+// int step_;
+// NodeMap pre_nodes_;
+// NodeMap post_nodes_;
+// LinkMap pre_links_;
+// LinkMap post_links_;
+// bool prob_changed_;
+// bool util_changed_;
+// Utility_Info pos_util_;
+// Utility_Info neg_util_;
+// Probability_Info true_prob_;
+// Probability_Info false_prob_;
+};
+
Node::~Node ()
{
// Nothing to do.
@@ -93,7 +137,7 @@ std::string Node::get_name (void)
/// Set activity flag
void Node::set_activity (bool state)
{
- active = state;
+ this->active_ = state;
}
NodeID Node::get_ID (void)
@@ -120,10 +164,52 @@ const LinkMap& Node::get_post (void)
TaskNode::TaskNode (NodeID ID, std::string name, MultFactor atten_factor,
TaskCost cost, Probability prior_prob)
: Node (ID, name, atten_factor),
- cost_ (cost),
- prior_prob_ (prior_prob)
+ prior_prob_ (prior_prob),
+ cost_ (cost)
{
- // Nothing to do.
+ // Initialize (empty) pre-node maps (true/false conditional probabilities for preconditions).
+ this->pre_true_probs_.clear ();
+ this->pre_false_probs_.clear ();
+};
+
+// Copy constructor. Performs initialization by making a deep copy
+// of the provided node (with the exception of network structural
+// information about other nodes).
+// (WARNING: Links, including their probability values and node
+// pointers, to & from this node are EMPTY in the newly created copy.)
+TaskNode::TaskNode (const TaskNode &s)
+: Node (s),
+ prior_prob_ (s.prior_prob_),
+ cost_ (s.cost_)
+{
+ // Initialize (EMPTY) pre-node maps (true/false conditional probabilities for preconditions).
+ this->pre_true_probs_.clear ();
+ this->pre_false_probs_.clear ();
+
+ // All other data members initialized to copy values by base class.
+
+// Node data members.
+// NodeID ID_;
+// bool active_;
+// std::string name_;
+// MultFactor atten_factor_;
+// int step_;
+// NodeMap pre_nodes_;
+// NodeMap post_nodes_;
+// LinkMap pre_links_;
+// LinkMap post_links_;
+// bool prob_changed_;
+// bool util_changed_;
+// Utility_Info pos_util_;
+// Utility_Info neg_util_;
+// Probability_Info true_prob_;
+// Probability_Info false_prob_;
+
+// TaskNode additional data members.
+// Probability prior_prob_;
+// TaskCost cost_;
+// LinkMap pre_true_probs_;
+// LinkMap pre_false_probs_;
};
TaskNode::~TaskNode (void)
@@ -145,7 +231,7 @@ bool TaskNode::update (void)
{
//Check to see if node is active before updating
- if(!active)
+ if(!(this->active_))
{
//the node should return as not changing the network
step_++;
@@ -734,6 +820,27 @@ void TaskNode::add_precond (CondID ID, CondNode *node, Probability true_prob,
node->add_post_link (ID_, this, weight);
};
+// Get conditional probability of success for a particular precondition.
+ConditionalProb TaskNode::get_precond_prob (CondID cond_ID)
+{
+ // Find conditional probability of success when precondition is true.
+ SANet::LinkMap::iterator link_true_iter = this->pre_true_probs_.find (cond_ID);
+ if (link_true_iter == this->pre_true_probs_.end ())
+ throw UnknownNode ();
+
+ // Find conditional probability of success when precondition is false.
+ SANet::LinkMap::iterator link_false_iter = this->pre_false_probs_.find (cond_ID);
+ if (link_false_iter == this->pre_false_probs_.end ())
+ throw UnknownNode ();
+
+ // Create conditional probability structure with true and false conditional probabilities.
+ ConditionalProb precond_prob;
+ precond_prob.true_prob = link_true_iter->second;
+ precond_prob.false_prob = link_false_iter->second;
+
+ return precond_prob;
+};
+
void TaskNode::add_effect (CondID ID, CondNode *node, LinkWeight weight)
{
// Add node to post-nodes.
@@ -769,6 +876,17 @@ void TaskNode::update_effect (CondID ID, CondNode *node, LinkWeight weight)
node->update_pre_link (ID_, this, weight);
};
+// Get probability of effect (link weight) for a particular effect condition.
+Probability TaskNode::get_effect_prob (CondID cond_ID)
+{
+ // Find probability of effect.
+ SANet::LinkMap::iterator link_iter = this->post_links_.find (cond_ID);
+ if (link_iter == this->post_links_.end ())
+ throw UnknownNode ();
+
+ return link_iter->second;
+};
+
Probability TaskNode::get_prior (void)
{
return prior_prob_;
@@ -807,6 +925,46 @@ CondNode::CondNode (CondID ID, std::string name, MultFactor atten_factor,
}
};
+// Copy constructor. Performs initialization by making a deep copy
+// of the provided node (with the exception of network structural
+// information about other nodes).
+// (WARNING: Links, including their probability values and node
+// pointers, to & from this node are EMPTY in the newly created copy.)
+CondNode::CondNode (const CondNode &s)
+: Node (s),
+ goal_util_ (s.goal_util_),
+ init_true_prob_ (s.init_true_prob_),
+ true_prob_from_ (s.true_prob_from_),
+ false_prob_from_ (s.false_prob_from_),
+ cond_kind_ (s.cond_kind_)
+{
+ // All other data members initialized to copy values by base class.
+
+// Node data members.
+// NodeID ID_;
+// bool active_;
+// std::string name_;
+// MultFactor atten_factor_;
+// int step_;
+// NodeMap pre_nodes_;
+// NodeMap post_nodes_;
+// LinkMap pre_links_;
+// LinkMap post_links_;
+// bool prob_changed_;
+// bool util_changed_;
+// Utility_Info pos_util_;
+// Utility_Info neg_util_;
+// Probability_Info true_prob_;
+// Probability_Info false_prob_;
+
+// CondNode additional data members.
+// Utility goal_util_;
+// Probability init_true_prob_;
+// TaskID true_prob_from_;
+// TaskID false_prob_from_;
+// CondKind cond_kind_;
+};
+
CondNode::~CondNode (void)
{
// Nothing to do.
@@ -1001,7 +1159,7 @@ bool CondNode::update (void)
{
//Check to see if node is active before updating
- if(!active)
+ if(!(this->active_))
{
step_++;
//the node should return as not changing the network
diff --git a/SA_POP/SANet/SANode.h b/SA_POP/SANet/SANode.h
index 4a205e86183..2a344adf09b 100644
--- a/SA_POP/SANet/SANode.h
+++ b/SA_POP/SANet/SANode.h
@@ -77,6 +77,16 @@ namespace SANet {
*/
Node (NodeID ID, std::string name, MultFactor atten_factor);
+ /// Copy constructor. Performs initialization by making a deep copy
+ /// of the provided node (with the exception of network structural
+ /// information about other nodes).
+ /// (WARNING: Links, including their probability values and node
+ /// pointers, to & from this node are EMPTY in the newly created copy.)
+ /**
+ * @param s Node to copy.
+ */
+ Node (const Node &s);
+
/// Destructor.
virtual ~Node ();
@@ -165,7 +175,7 @@ namespace SANet {
void reset_step();
bool is_active(){
- return active;
+ return active_;
}
protected:
@@ -173,7 +183,7 @@ namespace SANet {
NodeID ID_;
/// Flag indicating whether the node is active.
- bool active;
+ bool active_;
/// Name of node (descriptive only).
std::string name_;
@@ -240,6 +250,16 @@ namespace SANet {
TaskNode (TaskID ID, std::string name, MultFactor atten_factor, TaskCost cost,
Probability prior_prob);
+ /// Copy constructor. Performs initialization by making a deep copy
+ /// of the provided node (with the exception of network structural
+ /// information about other nodes).
+ /// (WARNING: Links, including their probability values and node
+ /// pointers, to & from this node are EMPTY in the newly created copy.)
+ /**
+ * @param s Task node to copy.
+ */
+ TaskNode (const TaskNode &s);
+
/// Destructor.
virtual ~TaskNode (void);
@@ -296,20 +316,15 @@ namespace SANet {
*/
virtual Utility get_utility (int step);
- /// Get Prior of the TaskNode.
+ /// Get prior probability of the task.
/**
- *
- *
- * @return Expected utility.
+ * @return Prior probability of the task.
*/
virtual Probability get_prior (void);
- /// Update Prior of the TaskNode.
+ /// Update prior probability of the task.
/**
- *
- * @param prior the new prior for the task
- *
- *
+ * @param prior The new prior probability of the task.
*/
virtual void update_prior (Probability prior);
@@ -329,11 +344,19 @@ namespace SANet {
virtual void add_precond (CondID ID, CondNode *node, Probability true_prob,
Probability false_prob);
+ /// Get conditional probability of success for a particular precondition.
+ /**
+ * @param cond_ID Precondition node.
+ *
+ * @return Conditional probability of the link.
+ */
+ virtual ConditionalProb get_precond_prob (CondID cond_ID);
+
/// Add effect link.
/**
- * @param ID Node ID.
+ * @param ID ID of effect condition node ID.
*
- * @param node Node pointer.
+ * @param node Pointer to effect condition node.
*
* @param weight Link weight (probability task sets condition to
* true, or negative of the probability task sets condition to false).
@@ -342,7 +365,7 @@ namespace SANet {
/// Update effect link.
/**
- * @param ID Node ID.
+ * @param ID ID of effect condition node ID.
*
* @param node Node pointer.
*
@@ -351,6 +374,14 @@ namespace SANet {
*/
virtual void update_effect (CondID ID, CondNode *node, LinkWeight weight);
+ /// Get probability of effect (link weight) for a particular effect condition.
+ /**
+ * @param cond_ID Effect condition node ID.
+ *
+ * @return Conditional probability of the link.
+ */
+ virtual Probability get_effect_prob (CondID cond_ID);
+
void set_pos_util(double util);
Utility_Info get_pos_util();
@@ -397,6 +428,16 @@ namespace SANet {
CondNode (CondID ID, std::string name, MultFactor atten_factor,
Probability true_prob, Probability false_prob, Utility goal_util, CondKind cond_kind);
+ /// Copy constructor. Performs initialization by making a deep copy
+ /// of the provided node (with the exception of network structural
+ /// information about other nodes).
+ /// (WARNING: Links, including their probability values and node
+ /// pointers, to & from this node are EMPTY in the newly created copy.)
+ /**
+ * @param s Condition node to copy.
+ */
+ CondNode (const CondNode &s);
+
/// Destructor.
virtual ~CondNode (void);
diff --git a/SA_POP/SA_POP_Types.h b/SA_POP/SA_POP_Types.h
index 5cf91c6b04d..ba17bf3feea 100644
--- a/SA_POP/SA_POP_Types.h
+++ b/SA_POP/SA_POP_Types.h
@@ -36,7 +36,7 @@
#define SA_POP_DEBUG_VERBOSE 30
// SET current SA-POP Debug output level.
-#define SA_POP_DEBUG_LEVEL SA_POP_DEBUG_QUIET
+#define SA_POP_DEBUG_LEVEL SA_POP_DEBUG_VERBOSE
#define _CRTDBG_MAP_ALLOC
#if defined (SA_POP_HAS_ACE)
@@ -124,6 +124,22 @@ namespace SA_POP {
/// Type of a probability.
typedef EUCalc Probability;
+ /// Type of a conditional probability.
+ struct ConditionalProb {
+ // Probability when conditioned variable is true.
+ Probability true_prob;
+ // Probability when conditioned variable is false.
+ Probability false_prob;
+ bool operator== (const ConditionalProb &s) const { return this->true_prob == s.true_prob && this->false_prob == s.false_prob; };
+ bool operator!= (const ConditionalProb &s) const { return !(*this == s); };
+ bool operator< (const ConditionalProb &s) const
+ {
+ if (this->true_prob == s.true_prob)
+ return this->false_prob < s.false_prob;
+ return this->true_prob < s.true_prob;
+ };
+ };
+
/// Type of a (precondition or effect) link weight.
typedef EUCalc LinkWeight;
diff --git a/SA_POP/Standalone/SAPOP_Demo.mpc b/SA_POP/Standalone/SAPOP_Demo.mpc
index ec49404f256..53194eeec62 100644
--- a/SA_POP/Standalone/SAPOP_Demo.mpc
+++ b/SA_POP/Standalone/SAPOP_Demo.mpc
@@ -1,16 +1,17 @@
project(SA_POP_Demo) : xerces, aceexe, sapop_core_standalone {
exename = SA_POP_Demo
- Source_Files {
- SA_POP_Demo.cpp
- UserInput.cpp
- }
+ includes += $(SAPOP_ROOT)/UserInput
- Inline_Files {
+ Header_Files {
+ $(SAPOP_ROOT)/UserInput/InputCL.h
+ $(SAPOP_ROOT)/UserInput/Question.h
}
- Header_Files {
- UserInput.h
+ Source_Files {
+ SA_POP_Demo.cpp
+
+ $(SAPOP_ROOT)/UserInput/InputCL.cpp
}
Documentation_Files {
diff --git a/SA_POP/Standalone/SA_POP_Demo.cpp b/SA_POP/Standalone/SA_POP_Demo.cpp
index b0f3e2d5f3e..64c916bef4f 100644
--- a/SA_POP/Standalone/SA_POP_Demo.cpp
+++ b/SA_POP/Standalone/SA_POP_Demo.cpp
@@ -14,49 +14,57 @@
#include <iostream>
#include "SA_POP_Types.h"
#include "SA_Builder.h"
-#include "UserInput.h"
#include "TaskMapFileIn.h"
#include "SANet/SANetFileIn.h"
#include "LogScreenOut.h"
+#include "InputCL.h"
+
+
+// SA-POP DEFAULTS.
+namespace SA_POP {
+ namespace Default {
+ const SA_POP::CondID CondIDMin = 1;
+ const SA_POP::CondID CondIDMax = 999999;
+ const SA_POP::Utility GoalUtilMin = -1000;
+ const SA_POP::Utility GoalUtilMax = 1000;
+ }; /* SA_POP::Default namespace */
+}; /* SA_POP namespace */
+
+// SPREADING ACTIVATION DEFAULTS.
+namespace SANet {
+ namespace Default {
+ const size_t SA_MAX_STEPS = 1000;
+ }; /* SANet::Default namespace */
+}; /* SANet namespace */
+
+
int main (int argc, char* argv[])
{
SA_POP::SA_Builder builder;
SANet::SANetFileIn sanet_in;
SA_POP::TaskMapFileIn tm_in;
+ SA_POP::Planner *planner = 0;
+ UserInterface::InputCL user_input;
+
std::string sanet_filename = "";
std::string tm_filename = "";
+ SA_POP::CondID goal_id = 0;
+ SA_POP::Utility goal_util = 0;
+ size_t max_steps = SANet::Default::SA_MAX_STEPS;
- // Get filenames from user.
- std::cout << "Task Network file: ";
-// sanet_filename = "../examples/output1.xml";
-// sanet_filename = "../examples/SPACE.san.xml";
-// sanet_filename = "../examples/test_graph1.san.xml";
- std::cin >> sanet_filename;
-
- std::cout << "Task Map file: ";
-// tm_filename = "../examples/SPACE.tm.xml";
-// tm_filename = "../examples/test_graph.tm.xml";
- std::cin >> tm_filename;
- SA_POP::Goal goal;
- goal.goal_id = "UserSpecifiedGoal ID";
- goal.name = "User specified goal";
- goal.abs_times.clear ();
- goal.rel_times.clear ();
- goal.goal_conds.clear ();
- goal.start_window = std::make_pair (0, 0);
+ // Get filenames from user.
+ UserInterface::Question sanet_file_ques ("Task Network file:");
+ if (user_input.ask (sanet_file_ques))
+ sanet_filename = sanet_file_ques.get_answer ();
+ UserInterface::Question tm_file_ques ("Task Map file:");
+ if (user_input.ask (tm_file_ques))
+ tm_filename = tm_file_ques.get_answer ();
- // Get goal.
- SA_POP::CondID goal_id;
- SA_POP::Utility goal_util;
- std::cout << "Goal condition ID: ";
- std::cin >> goal_id;
- std::cout << "Goal utility: ";
- std::cin >> goal_util;
- goal.goal_conds.insert (std::make_pair (goal_id, goal_util));
+ // Build task network and task map.
try {
sanet_in.build_net (sanet_filename, &builder);
tm_in.build_task_map (tm_filename, &builder);
@@ -65,19 +73,45 @@ int main (int argc, char* argv[])
std::cerr << std::endl;
std::cerr << e;
} catch (...) {
- std::cerr << "UNKNOWN ERROR while planning." << std::endl;
+ std::cerr << "UNKNOWN ERROR while building task network and task map from files." << std::endl;
}
- SA_POP::Planner *planner = 0;
+ // Create goal.
+ SA_POP::Goal goal;
+ goal.goal_id = "UserSpecifiedGoal ID";
+ goal.name = "User specified goal";
+ goal.abs_times.clear ();
+ goal.rel_times.clear ();
+ goal.goal_conds.clear ();
+ goal.start_window = std::make_pair (0, 0);
+
+ // Get goal condition and utility from user.
+ UserInterface::QuestionInt goal_id_ques ("Goal condition ID:", SA_POP::Default::CondIDMin, SA_POP::Default::CondIDMax);
+ if (user_input.ask (goal_id_ques))
+ goal_id = goal_id_ques.get_answer_int ();
+ UserInterface::QuestionInt goal_util_ques ("Goal utility:", SA_POP::Default::GoalUtilMin, SA_POP::Default::GoalUtilMax);
+ if (user_input.ask (goal_util_ques))
+ goal_util = goal_util_ques.get_answer_int ();
+
+ goal.goal_conds.insert (std::make_pair (goal_id, goal_util));
+
+
+ // Get maximum steps of spreading activation from user.
+ UserInterface::QuestionInt steps_ques("Max steps to run (10000 step limit): ", 0, 10000);
+ if (user_input.ask (steps_ques))
+ max_steps = steps_ques.get_answer_int ();
+
+
+ // Run SA-POP.
try {
planner = builder.get_planner ();
SA_POP::LogScreenOut screen_out (std::cout);
planner->add_out_adapter (&screen_out);
- planner->plan (100, goal);
+ planner->plan (max_steps, goal);
} catch (std::string e) {
std::cerr << "ERROR while planning:" << std::endl;
std::cerr << e;
@@ -89,11 +123,9 @@ int main (int argc, char* argv[])
delete planner;
-//****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP
- std::cout << "Enter any character to end program: ";
- char temp_;
- std::cin>>temp_;
-//****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP
+ // Wait for user to end program.
+// UserInterface::Question end_ques ("Enter any character to end program:");
+// user_input.ask (end_ques);
return 0;
}
diff --git a/SA_POP/Standalone/UserInput.cpp b/SA_POP/Standalone/UserInput.cpp
deleted file mode 100644
index a216b91cbff..00000000000
--- a/SA_POP/Standalone/UserInput.cpp
+++ /dev/null
@@ -1,33 +0,0 @@
-// -*- C++ -*-
-// $Id$
-
-//=============================================================================
-/**
- * @file UserInput.cpp
- *
- * This file contains the UserInput class implementation for the input adapter
- * that provides a user interface for testing SA-POP.
- *
- * @author John S. Kinnebrew <john.s.kinnebrew@vanderbilt.edu>
- */
-//=============================================================================
-
-#include "SA_POP_Types.h"
-#include "UserInput.h"
-#include "Builder.h"
-#include "Planner.h"
-
-
-using namespace SA_POP;
-
-// Constructor.
-UserInput::UserInput (void)
-{
- //****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP
-};
-
-// Destructor.
-UserInput::~UserInput (void)
-{
- //****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP****TEMP
-};
diff --git a/SA_POP/Standalone/UserInput.h b/SA_POP/Standalone/UserInput.h
deleted file mode 100644
index b1b2b52111c..00000000000
--- a/SA_POP/Standalone/UserInput.h
+++ /dev/null
@@ -1,42 +0,0 @@
-// -*- C++ -*-
-// $Id$
-
-//=============================================================================
-/**
- * @file UserInput.h
- *
- * This file contains the UserInput class definition for the input adapter
- * that provides a user interface for testing SA-POP.
- *
- * @author John S. Kinnebrew <john.s.kinnebrew@vanderbilt.edu>
- */
-//=============================================================================
-
-#ifndef SA_POP_USER_INPUT_H_
-#define SA_POP_USER_INPUT_H_
-
-#include "SA_POP_Types.h"
-#include "UserInput.h"
-#include "Builder.h"
-#include "Planner.h"
-
-
-namespace SA_POP {
-
- /**
- * @class UserInput
- *
- * @brief Input adapter that provides a user interface for testing SA-POP.
- */
- class UserInput {
- public:
- /// Constructor.
- UserInput (void);
-
- /// Destructor.
- virtual ~UserInput (void);
- };
-
-}; /* SA_POP namespace */
-
-#endif /* SA_POP_USER_INPUT_H_ */
diff --git a/SA_POP/UserInput/InputCL.cpp b/SA_POP/UserInput/InputCL.cpp
new file mode 100644
index 00000000000..b097a6d96b7
--- /dev/null
+++ b/SA_POP/UserInput/InputCL.cpp
@@ -0,0 +1,152 @@
+// -*- C++ -*-
+// $Id$
+
+//=============================================================================
+/**
+ * @file InputCL.cpp
+ *
+ * This file contains the InputCL class implementation for the command line
+ * input adapter (helper class for command line interfaces).
+ *
+ * @author John S. Kinnebrew <john.s.kinnebrew@vanderbilt.edu>
+ */
+//=============================================================================
+
+#include <iostream>
+#include <string>
+
+#include "InputCL.h"
+#include "Question.h"
+
+using namespace UserInterface;
+
+// Constructor.
+InputCL::InputCL (std::basic_ostream<char, std::char_traits<char> >& ostrm,
+ std::basic_istream<char, std::char_traits<char> >& istrm)
+: ostrm_ (ostrm),
+ istrm_ (istrm)
+{
+ // Nothing to initialize.
+};
+
+// Destructor.
+InputCL::~InputCL (void)
+{
+ // Nothing to do.
+};
+
+// Provide info to user.
+void InputCL::info (UserInterface::Question info)
+{
+ this->ostrm_ << info.get_prompt ();
+ this->ostrm_ << std::endl;
+};
+
+// Ask the user a question (continues asking until they provide a valid answer).
+bool InputCL::ask (UserInterface::Question& question, size_t max_repeat)
+{
+ // Display question and get answer until receiving a valid response or maximum
+ // number of repeats has been reached.
+ std::string answer = "";
+ for (size_t reps = 0; reps < max_repeat; reps++) {
+ // Display question.
+ this->ostrm_ << question.get_prompt ();
+ this->ostrm_ << " ";
+
+ // Get answer.
+ this->istrm_ >> answer;
+
+ // Break out of question asking loop if user provided a valid answer.
+ if (question.is_valid_answer (answer))
+ break;
+
+ // User provided an invalid answer, so display response.
+ this->ostrm_ << question.get_invalid_response ();
+ this->ostrm_ << std::endl;
+ }
+
+ // Set answer in question object and return flag indicating its validity.
+ return question.answer (answer);
+};
+
+
+
+
+
+
+
+// Constructor.
+QuestionInt::QuestionInt (std::string prompt, int min, int max, std::string invalid_response)
+: Question (prompt, invalid_response),
+ min_ (min),
+ max_ (max)
+{
+ // Nothing to do.
+};
+
+// Destructor.
+QuestionInt::~QuestionInt (void)
+{
+ // Nothing to do.
+};
+
+// Is an answer valid for this question?
+bool QuestionInt::is_valid_answer (std::string answer)
+{
+ int i;
+ std::istringstream answer_ss (answer);
+
+ if (answer_ss >> i)
+ {
+ if (i >= this->min_ && i <= this->max_)
+ return true;
+ }
+
+ return false;
+};
+
+// Get answer.
+int QuestionInt::get_answer_int ()
+{
+ int i = 0;
+ std::istringstream answer_ss (this->answer_);
+
+ if (answer_ss >> i)
+ return i;
+
+ return this->min_;
+};
+
+
+
+
+
+// Constructor
+QuestionBool::QuestionBool (std::string prompt, bool def_val, std::string invalid_response)
+: QuestionChoice (prompt, def_val, false, invalid_response)
+{
+ this->init_map ();
+};
+
+// Destructor.
+QuestionBool::~QuestionBool (void)
+{
+ // Nothing to do.
+};
+
+// Get answer.
+bool QuestionBool::get_answer_bool (void)
+{
+ return this->get_answer_val ();
+};
+
+// Initialize mapping with yes/no answers.
+void QuestionBool::init_map (void)
+{
+ this->answer_map_.clear ();
+ this->add_mapping ("Y", true);
+ this->add_mapping ("Yes", true);
+ this->add_mapping ("N", false);
+ this->add_mapping ("No", false);
+};
+
diff --git a/SA_POP/UserInput/InputCL.h b/SA_POP/UserInput/InputCL.h
new file mode 100644
index 00000000000..2656c967b6d
--- /dev/null
+++ b/SA_POP/UserInput/InputCL.h
@@ -0,0 +1,166 @@
+// -*- C++ -*-
+// $Id$
+
+//=============================================================================
+/**
+ * @file InputCL.h
+ *
+ * This file contains the class definition of InputCL and related classes for
+ * the command line input adapter (helper class for command line interfaces).
+ *
+ * @author John S. Kinnebrew <john.s.kinnebrew@vanderbilt.edu>
+ */
+//=============================================================================
+
+#ifndef USER_INTERFACE_INPUT_CL_H_
+#define USER_INTERFACE_INPUT_CL_H_
+
+#include <iostream>
+#include <string>
+
+#include "Question.h"
+
+namespace UserInterface {
+
+ namespace Default {
+ const size_t MAX_QUESTION_REPEAT = 5;
+ }; /* Default namespace */
+
+
+ /**
+ * @class InputCL
+ *
+ * @brief Command line input adapter (helper class for command line interfaces).
+ */
+ class InputCL {
+ public:
+ /// Constructor.
+ /**
+ * @param ostrm Output stream to display questions/prompts and info to user.
+ *
+ * @param istrm Input stream to get user input.
+ */
+ InputCL (std::basic_ostream<char, std::char_traits<char> >& ostrm
+ = std::cout, std::basic_istream<char, std::char_traits<char> >& istrm
+ = std::cin);
+
+ /// Destructor.
+ virtual ~InputCL (void);
+
+ /// Provide info to user.
+ /**
+ * @param info Question class with info for user.
+ */
+ void info (UserInterface::Question info);
+
+ /// Ask the user a question.
+ /**
+ * @param question Question for user (question object will be updated with last user answer upon return).
+ *
+ * @param max_repeat Maximum number of times to repeat question when user provides invalid answer(s).
+ *
+ * @return True if user provided a valid answer to question, false otherwise.
+ */
+ bool ask (UserInterface::Question& question, size_t max_repeat = UserInterface::Default::MAX_QUESTION_REPEAT);
+
+ protected:
+ /// Output stream to display questions/prompts and info to user.
+ std::basic_ostream<char, std::char_traits<char> >& ostrm_;
+
+ /// Input stream to get user input.
+ std::basic_istream<char, std::char_traits<char> >& istrm_;
+ };
+
+
+
+
+
+
+
+
+
+
+
+
+
+ /**
+ * @class QuestionInt
+ *
+ * @brief Class for a user question with an integer answer.
+ */
+ class QuestionInt : public Question {
+ public:
+ /// Constructor.
+ /**
+ * @param prompt Prompt/question for user.
+ *
+ * @param min Minimum (inclusive) valid answer.
+ *
+ * @param max Maximum (inclusive) valid answer.
+ *
+ * @param invalid_response Response string for when user provides an invalid answer.
+ */
+ QuestionInt (std::string prompt, int min, int max, std::string invalid_response = UserInterface::Default::INVALID_RESPONSE_STR);
+
+ /// Destructor.
+ virtual ~QuestionInt (void);
+
+ /// Is an answer valid for this question?
+ /**
+ * @param answer Answer to check validity.
+ *
+ * @return True for a valid answer or false for an invalid answer.
+ */
+ virtual bool is_valid_answer (std::string answer);
+
+ /// Get answer.
+ /**
+ * @return Answer from user (if no valid answer provided, returns minimum valid answer).
+ */
+ int get_answer_int (void);
+
+ protected:
+ /// Minimum (inclusive) valid answer.
+ int min_;
+
+ /// Maximum (inclusive) valid answer.
+ int max_;
+
+ };
+
+ /**
+ * @class QuestionBool
+ *
+ * @brief Class for a user question with a boolean (yes/no) answer.
+ * Valid answer strings (case insensitive) corresponding to true are "y" and "yes".
+ * Valid answer strings (case insensitive) corresponding to false are "n" and "no".
+ */
+ class QuestionBool : public QuestionChoice<bool> {
+ public:
+ /// Constructor.
+ /**
+ * @param prompt Prompt/question (or info) for user.
+ *
+ * @param def_val Default value returned if no valid answer provided.
+ *
+ * @param invalid_response Response string for when user provides an invalid answer.
+ */
+ QuestionBool (std::string prompt, bool def_val, std::string invalid_response = UserInterface::Default::INVALID_RESPONSE_STR);
+
+ /// Destructor.
+ virtual ~QuestionBool (void);
+
+ /// Get answer.
+ /**
+ * @return Answer from user (if no valid answer provided, returns default value).
+ */
+ bool get_answer_bool (void);
+
+ protected:
+ /// Initialize mapping with yes/no answers.
+ void init_map (void);
+ };
+
+}; /* UserInterface namespace */
+
+#endif /* USER_INTERFACE_INPUT_CL_H_ */
diff --git a/SA_POP/UserInput/Question.cpp b/SA_POP/UserInput/Question.cpp
new file mode 100644
index 00000000000..14ffb39905d
--- /dev/null
+++ b/SA_POP/UserInput/Question.cpp
@@ -0,0 +1,124 @@
+// -*- C++ -*-
+// $Id$
+
+//=============================================================================
+/**
+ * @file Question.cpp
+ *
+ * This file contains the implementation of Question classes for use with
+ * the command line input adapter (InputCL).
+ *
+ * @author John S. Kinnebrew <john.s.kinnebrew@vanderbilt.edu>
+ */
+//=============================================================================
+
+#ifndef USER_INTERFACE_QUESTION_CPP_
+#define USER_INTERFACE_QUESTION_CPP_
+
+#include <string>
+#include <sstream>
+#include <map>
+#include <algorithm>
+
+#include "Question.h"
+
+using namespace UserInterface;
+
+
+
+// Constructor.
+template <typename T>
+QuestionChoice<T>::QuestionChoice (std::string prompt, T invalid_val, bool match_case, std::string invalid_response)
+: Question (prompt, invalid_response),
+ invalid_val_ (invalid_val),
+ match_case_ (match_case)
+{
+ // Clear map from answers to values.
+ this->answer_map_.clear ();
+};
+
+// Destructor.
+template <typename T>
+QuestionChoice<T>::~QuestionChoice (void)
+{
+ // Nothing to do.
+};
+
+// Is an answer valid for this question?
+template <typename T> bool
+QuestionChoice<T>::is_valid_answer (std::string answer)
+{
+ std::string ans = answer;
+
+ // If case insensitive, convert answer to upper case before checking answer map.
+ if (!this->match_case_)
+ std::transform(ans.begin(), ans.end(), ans.begin(), ::toupper);
+
+ // If answer is not in answer map, it is not valid.
+ if (this->answer_map_.find (ans) == this->answer_map_.end ())
+ return false;
+
+ return true;
+};
+
+// Get answer.
+template <typename T> T
+QuestionChoice<T>::get_answer_val (void)
+{
+ std::string ans = this->answer_;
+
+ // If case insensitive, convert answer to upper case before checking answer map.
+ if (!this->match_case_)
+ std::transform(ans.begin(), ans.end(), ans.begin(), ::toupper);
+
+ // Find answer in answer map.
+ std::map<std::string, T>::iterator answer_iter = this->answer_map_.find (ans);
+
+ // If answer is not in answer map, return invalid value.
+ if (answer_iter == this->answer_map_.end ())
+ return this->invalid_val_;
+
+ return answer_iter->second;
+};
+
+// Set complete mapping from answers to values.
+// (WARNING: Map will completely replace all existing mappings.)
+template <typename T> void
+QuestionChoice<T>::set_map (const std::map<std::string, T> &answer_map)
+{
+ // Overwrite current mapping with new mapping (converting answers
+ // to upper case, if not case sensitive).
+ if (this->match_case_) {
+ this->answer_map_ = answer_map;
+ } else {
+ // Clear current map.
+ this->answer_map_.clear ();
+
+ // Convert each answer to upper case and insert with value into answer map.
+ std::string ans = "";
+ for (std::map<std::string, T>::const_iterator ans_iter = answer_map.begin (); ans_iter != answer_map; ans_iter++) {
+ ans = ans_iter->first;
+ std::transform(ans.begin(), ans.end(), ans.begin(), ::toupper);
+ this->answer_map_.insert (std::make_pair (ans, ans_iter->second));
+ }
+ }
+};
+
+// Add a mapping from an answer to a value (or replace with provided
+// value if a mapping already exists for the answer).
+template <typename T> void
+QuestionChoice<T>::add_mapping (std::string answer, T value)
+{
+ std::string ans = answer;
+
+ // If case insensitive, convert answer to upper case before inserting in answer map.
+ if (!this->match_case_)
+ std::transform(ans.begin(), ans.end(), ans.begin(), ::toupper);
+
+ this->answer_map_.insert (std::make_pair (ans, value));
+};
+
+
+
+
+#endif /* USER_INTERFACE_QUESTION_CPP_ */
diff --git a/SA_POP/UserInput/Question.h b/SA_POP/UserInput/Question.h
new file mode 100644
index 00000000000..05e841cb83c
--- /dev/null
+++ b/SA_POP/UserInput/Question.h
@@ -0,0 +1,172 @@
+// -*- C++ -*-
+// $Id$
+
+//=============================================================================
+/**
+ * @file Question.h
+ *
+ * This file contains the declarations of Question classes for use with
+ * the command line input adapter (InputCL).
+ *
+ * @author John S. Kinnebrew <john.s.kinnebrew@vanderbilt.edu>
+ */
+//=============================================================================
+
+#ifndef USER_INTERFACE_QUESTION_H_
+#define USER_INTERFACE_QUESTION_H_
+
+#include <string>
+#include <sstream>
+#include <map>
+
+namespace UserInterface {
+
+ namespace Default {
+ const std::string INVALID_RESPONSE_STR = "Sorry, that is not a valid answer.";
+ }; /* Default namespace */
+
+ /**
+ * @class Question
+ *
+ * @brief Base class for a user question (or info for user).
+ */
+ class Question {
+ public:
+ /// Constructor.
+ /**
+ * @param prompt Prompt/question (or info) for user.
+ *
+ * @param invalid_response Response string for when user provides an invalid answer.
+ */
+ Question (std::string prompt, std::string invalid_response = UserInterface::Default::INVALID_RESPONSE_STR)
+ : prompt_ (prompt), invalid_response_ (invalid_response), answer_ ("") { };
+
+ /// Destructor.
+ virtual ~Question (void) { };
+
+ /// Set prompt.
+ /**
+ * @param prompt Prompt/question (or info) for user.
+ */
+ void set_prompt (std::string prompt) { this->prompt_ = prompt; };
+
+ /// Get prompt.
+ /**
+ * @return Prompt/question (or info) for user.
+ */
+ std::string get_prompt () { return this->prompt_; };
+
+ /// Get response string for when user provides an invalid answer.
+ /**
+ * @return Response string for when user provides an invalid answer.
+ */
+ std::string get_invalid_response () { return this->invalid_response_; };
+
+ /// Is an answer valid for this question?
+ /**
+ * @param answer Answer to check validity.
+ *
+ * @return True for a valid answer or false for an invalid answer.
+ */
+ virtual bool is_valid_answer (std::string answer) { return true; };
+
+ /// Provide user answer.
+ /**
+ * @param answer User answer.
+ *
+ * @return True for a valid answer or false for an invalid answer.
+ */
+ virtual bool answer (std::string answer) { if (this->is_valid_answer (answer)) {this->answer_ = answer; return true;} return false; };
+
+ /// Get answer.
+ /**
+ * @return Answer from user (if no valid answer provided, returns empty string).
+ */
+ std::string get_answer () { return this->answer_; };
+
+ protected:
+ /// Prompt/question (or info) for user.
+ std::string prompt_;
+
+ /// Response to user when they provide an invalid answer to the question.
+ std::string invalid_response_;
+
+ /// Answer.
+ std::string answer_;
+ };
+
+
+ /**
+ * @class QuestionChoice
+ *
+ * @brief Class for a user question with a mapping from answers to values.
+ */
+ template <typename T>
+ class QuestionChoice : public Question {
+ public:
+ /// Class trait of its answer value type.
+ typedef T TYPE;
+
+ /// Constructor.
+ /**
+ * @param prompt Prompt/question for user.
+ *
+ * @param invalid_val Value to return if no valid answer provided.
+ *
+ * @param match_case Match case of answer strings? (i.e., case sensitive?)
+ *
+ * @param invalid_response Response string for when user provides an invalid answer.
+ */
+ QuestionChoice (std::string prompt, T invalid_val, bool match_case = false, std::string invalid_response = UserInterface::Default::INVALID_RESPONSE_STR);
+
+ /// Destructor.
+ virtual ~QuestionChoice (void);
+
+ /// Is an answer valid for this question?
+ /**
+ * @param answer Answer to check validity.
+ *
+ * @return True for a valid answer or false for an invalid answer.
+ */
+ virtual bool is_valid_answer (std::string answer);
+
+ /// Get answer.
+ /**
+ * @return Value corresponding to answer from user (if no valid answer provided, returns invalid_val parameter from constructor).
+ */
+ T get_answer_val (void);
+
+ /// Set complete mapping from answers to values.
+ /// (WARNING: Map will completely replace all existing mappings.)
+ /**
+ * @param answer_map Map from valid answer strings to corresponding values.
+ */
+ void set_map (const std::map<std::string, T> &answer_map);
+
+ /// Add a mapping from an answer to a value (or replace with provided
+ /// value if a mapping already exists for the answer).
+ /**
+ * @param answer Valid answer string.
+ *
+ * @param value Value corresponding to answer string.
+ */
+ void add_mapping (std::string answer, T value);
+
+ protected:
+ /// Match case of strings? (i.e., case sensitive?)
+ bool match_case_;
+
+ /// Value to indicate invalid answer.
+ T invalid_val_;
+
+ /// Map from answers to values.
+ std::map<std::string, T> answer_map_;
+ };
+
+
+
+}; /* UserInterface namespace */
+
+#include "Question.cpp"
+
+#endif /* USER_INTERFACE_QUESTION_H_ */