Skip to content
GitLab
Menu
Projects
Groups
Snippets
/
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
perception
imagine-planner
Commits
eb54b4f4
Commit
eb54b4f4
authored
Jan 28, 2018
by
Alejandro Suarez Hernandez
Browse files
small improvements
parent
d1b394e5
Changes
11
Hide whitespace changes
Inline
Side-by-side
src/blindsearch.cpp
View file @
eb54b4f4
#include
"blindsearch.h"
#include
<iostream>
#include
<queue>
#include
<unordered_map>
namespace
imagine_planner
{
void
BreadthFirstSearch
::
set_parameters
(
const
Parameters
&
params
)
{
verbose_
=
get_parameter
(
params
,
"verbose"
,
false
);
timeout_
=
get_parameter
(
params
,
"timeout"
,
0
);
max_nodes_
=
get_parameter
(
params
,
"max_nodes"
,
0
);
}
void
BreadthFirstSearch
::
do_search
(
const
Problem
&
problem
)
{
typedef
std
::
pair
<
PlanState
::
Ptr
,
Operator
>
Preceding
;
...
...
@@ -14,14 +20,15 @@ void BreadthFirstSearch::do_search(const Problem& problem)
std
::
queue
<
PlanState
::
Ptr
>
open
;
open
.
push
(
problem
.
start
);
tree
[
problem
.
start
]
=
Preceding
(
nullptr
,
Operator
());
int
iteration
=
0
;
int
expanded
=
0
;
int
generated
=
0
;
while
(
not
(
open
.
empty
()
or
timeout
()
or
memout
(
open
.
size
())))
{
PlanState
::
Ptr
state
=
open
.
front
();
open
.
pop
();
auto
all_ops
=
problem
.
domain
->
instantiate_all
(
state
);
stats_
[
"
expanded
"
]
+=
1
;
stats_
[
"
generated
"
]
+=
all_ops
.
size
();
expanded
+=
1
;
generated
+=
all_ops
.
size
();
for
(
const
Operator
&
op
:
all_ops
)
{
auto
successor
=
op
(
state
);
...
...
@@ -31,29 +38,37 @@ void BreadthFirstSearch::do_search(const Problem& problem)
if
((
*
problem
.
goal
)(
*
successor
))
{
/* Goal condition satisfied */
complete_stats
(
);
fill_stats
(
expanded
,
generated
);
result_
=
FOUND
;
plan_
=
Plan
::
reconstruct_path
(
problem
,
tree
,
successor
);
plan_
=
Plan
::
reconstruct_path
(
tree
,
successor
);
if
(
verbose_
)
{
PLANNER_LOG
(
"Plan with "
<<
plan_
.
size
()
<<
" action(s) found"
,
INFO
);
}
return
;
}
open
.
push
(
successor
);
}
}
if
(
verbose_
>
0
and
iteration
%
100
==
0
)
if
(
verbose_
and
expanded
%
100
==
1
)
{
/* log feedback */
std
::
cout
<<
"#expanded nodes: "
<<
stats_
[
"
expanded
"
]
<<
", #generated nodes: "
<<
stats_
[
"
generated
"
]
<<
std
::
endl
;
PLANNER_LOG
(
"#expanded nodes: "
<<
expanded
<<
", #generated nodes: "
<<
generated
,
INFO
)
;
}
++
iteration
;
}
/* Either unsolvable problem or timeout/memout */
complete_stats
();
if
(
open
.
empty
())
result_
=
UNSOLVABLE
;
fill_stats
(
expanded
,
generated
);
if
(
open
.
empty
())
{
result_
=
UNSOLVABLE
;
if
(
verbose_
)
PLANNER_LOG
(
"Unsolvable problem"
,
WARNING
);
}
else
{
result_
=
NOT_FOUND
;
msg_
=
timeout
()
?
"timeout"
:
"memout"
;
if
(
verbose_
)
PLANNER_LOG
(
"Could not solve problem: "
<<
msg_
,
ERROR
);
}
}
...
...
@@ -67,9 +82,11 @@ bool BreadthFirstSearch::memout(std::size_t open_size) const
return
max_nodes_
>
0
and
open_size
>
max_nodes_
;
}
void
BreadthFirstSearch
::
complete_stats
(
)
void
BreadthFirstSearch
::
fill_stats
(
double
expanded
,
double
generated
)
{
stats_
[
"branching"
]
=
stats_
[
"generated"
]
/
stats_
[
"expanded"
];
stats_
[
"expanded"
]
=
expanded
;
stats_
[
"generated"
]
=
generated
;
stats_
[
"branching"
]
=
generated
/
expanded
;
}
}
/* end namespace */
...
...
src/blindsearch.h
View file @
eb54b4f4
...
...
@@ -10,8 +10,9 @@ class BreadthFirstSearch : public Planner
{
public:
BreadthFirstSearch
(
int
verbose
=
0
,
double
timeout
=
0
,
std
::
size_t
max_nodes
=
0
)
:
verbose_
(
verbose
),
timeout_
(
timeout
),
max_nodes_
(
max_nodes
)
{}
BreadthFirstSearch
()
{
set_parameters
({});
}
virtual
void
set_parameters
(
const
Planner
::
Parameters
&
params
)
override
;
protected:
...
...
@@ -23,14 +24,66 @@ class BreadthFirstSearch : public Planner
bool
memout
(
std
::
size_t
open_size
)
const
;
void
complete_stats
(
);
void
fill_stats
(
double
expanded
,
double
generated
);
int
verbose_
;
bool
verbose_
;
double
timeout_
;
std
::
size_
t
max_nodes_
;
in
t
max_nodes_
;
};
// [TO DO] Iterative Deepening Search
// [TO DO] Re-implement Iterative Deepening Search
// Previous implementation of IDS
//class IDSPlanner : public Planner
//{
//private:
//typedef std::unordered_set<PlanState, std::hash<Hashable>> ClosedSet;
//const Problem* problem_;
//ClosedSet seen_;
//int max_depth_;
//double elapsed_;
//bool ids(const PlanState& state, Plan& plan, std::size_t depth)
//{
//if (problem_->goal(state)) return true;
//if (depth == 0) return false;
//seen_.insert(state);
//std::vector<Operator> instantiations = problem_->domain.instantiate_all(state);
//for (const Operator& op : instantiations)
//{
//PlanState next = op(state);
//if (seen_.count(next)) continue;
//plan.push_back({op, next});
//if (ids(next, plan, depth-1)) return true;
//plan.pop_back();
//}
//seen_.erase(state);
//return false;
//}
//public:
//IDSPlanner(int max_depth=100) : max_depth_(100) {}
//virtual Plan operator()(const Problem& problem) override
//{
//Plan plan;
//problem_ = &problem;
//StopWatch sw;
//for (int depth = 0; depth < max_depth_; ++depth)
//{
//if (ids(problem_->start, plan, depth)) break;
//}
//elapsed_ = sw.time();
//seen_.clear();
//return plan;
//}
//double get_elapsed() const { return elapsed_; }
//};
}
...
...
src/domains.cpp
View file @
eb54b4f4
...
...
@@ -9,6 +9,8 @@ namespace imagine_planner
// Implementation of Operator's methods
Operator
Operator
::
NOP
;
Operator
::
Operator
(
const
std
::
string
&
name
,
const
std
::
string
&
pre
,
const
std
::
string
&
eff
)
:
name_
(
name
)
{
...
...
@@ -42,12 +44,17 @@ std::string Operator::to_str() const
PlanState
::
Ptr
Operator
::
operator
()(
const
PlanState
::
Ptr
&
state
)
const
{
PlanState
::
Ptr
new_state
(
nullptr
);
if
(
not
is_ground
())
{
throw
ImaginePlannerException
(
"Trying to apply unground operator"
);
}
auto
new_state
=
std
::
make_shared
<
PlanState
>
(
*
state
);
(
*
eff_
)(
*
new_state
,
*
sigma_
);
if
(
is_nop
())
new_state
=
state
;
else
if
(
check_precondition
(
state
))
{
new_state
=
std
::
make_shared
<
PlanState
>
(
*
state
);
(
*
eff_
)(
*
new_state
,
*
sigma_
);
}
return
new_state
;
}
...
...
src/domains.h
View file @
eb54b4f4
...
...
@@ -16,6 +16,8 @@ class Operator : public Stringifiable
typedef
std
::
shared_ptr
<
const
Operator
>
Ptr
;
static
Operator
NOP
;
Operator
()
{}
Operator
(
const
std
::
string
&
name
,
const
Query
::
Ptr
&
pre
,
...
...
@@ -37,6 +39,8 @@ class Operator : public Stringifiable
bool
is_ground
()
const
{
return
(
bool
)
sigma_
;
}
bool
is_nop
()
const
{
return
name_
.
empty
();
}
bool
check_precondition
(
const
PlanState
::
Ptr
&
state
)
const
;
PlanState
::
Ptr
operator
()(
const
PlanState
::
Ptr
&
state
)
const
;
...
...
src/examples/imagine-planner_test.cpp
View file @
eb54b4f4
...
...
@@ -10,64 +10,14 @@ using namespace imagine_planner;
#if 1
#define INFO(x)\
std::cout << "\e[
1m\e[
32m\e[4m" << __PRETTY_FUNCTION__ << " [" << __LINE__ << "]" << "\e[24m: " << x << "\e[0m" << std::endl;
std::cout << "\e[32m\e[4m" << __PRETTY_FUNCTION__ << " [" << __LINE__ << "]" << "\e[24m: " << x << "\e[0m" << std::endl;
#else
#define INFO(x)
#endif
#define ERROR(x)\
std::cout << "\e[
1m\e[
31m\e[4m" << __PRETTY_FUNCTION__ << " [" << __LINE__ << "]" << "\e[24m: " << x << "\e[0m" << std::endl;
std::cout << "\e[31m\e[4m" << __PRETTY_FUNCTION__ << " [" << __LINE__ << "]" << "\e[24m: " << x << "\e[0m" << std::endl;
//class IDSPlanner : public Planner
//{
//private:
//typedef std::unordered_set<PlanState, std::hash<Hashable>> ClosedSet;
//const Problem* problem_;
//ClosedSet seen_;
//int max_depth_;
//double elapsed_;
//bool ids(const PlanState& state, Plan& plan, std::size_t depth)
//{
//if (problem_->goal(state)) return true;
//if (depth == 0) return false;
//seen_.insert(state);
//std::vector<Operator> instantiations = problem_->domain.instantiate_all(state);
//for (const Operator& op : instantiations)
//{
//PlanState next = op(state);
//if (seen_.count(next)) continue;
//plan.push_back({op, next});
//if (ids(next, plan, depth-1)) return true;
//plan.pop_back();
//}
//seen_.erase(state);
//return false;
//}
//public:
//IDSPlanner(int max_depth=100) : max_depth_(100) {}
//virtual Plan operator()(const Problem& problem) override
//{
//Plan plan;
//problem_ = &problem;
//StopWatch sw;
//for (int depth = 0; depth < max_depth_; ++depth)
//{
//if (ids(problem_->start, plan, depth)) break;
//}
//elapsed_ = sw.time();
//seen_.clear();
//return plan;
//}
//double get_elapsed() const { return elapsed_; }
//};
void
head_and_tail
(
const
std
::
string
&
rule
,
std
::
string
&
head
,
...
...
@@ -193,16 +143,19 @@ int main(int argc, char *argv[])
return
-
1
;
}
problem
.
domain
=
std
::
make_shared
<
Domain
>
(
domain_name
,
dbpath
,
0
);
BreadthFirstSearch
planner
(
1
);
BreadthFirstSearch
planner
;
planner
.
set_parameters
({{
"verbose"
,
"true"
}});
planner
.
set_logger
(
Logger
::
Ptr
(
new
StdLogger
));
planner
.
search
(
problem
);
Planner
::
Statistics
stats
=
planner
.
get_stats
();
INFO
(
"Initial state: "
<<
*
problem
.
start
);
INFO
(
"Goal condition: "
<<
*
problem
.
goal
);
INFO
(
"Plan found: "
<<
planner
.
get_plan
());
INFO
(
"Elapsed (ms): "
<<
stats
[
"elapsed"
]
*
1000
);
INFO
(
"#Expaned nodes: "
<<
stats
[
"expanded"
]);
INFO
(
"#Expan
d
ed nodes: "
<<
stats
[
"expanded"
]);
INFO
(
"#Generated nodes: "
<<
stats
[
"generated"
]);
INFO
(
"Avg. branching factor: "
<<
stats
[
"branching"
]);
INFO
(
"Message: "
<<
planner
.
get_message
());
//IDSPlanner planner(50);
//Plan plan = planner(problem);
//INFO("Initial state: " << problem.start);
...
...
src/imagine-planner.cpp
View file @
eb54b4f4
#include
"imagine-planner.h"
#include
<iostream>
#include
<sstream>
namespace
imagine_planner
...
...
@@ -18,25 +19,23 @@ std::string Plan::to_str() const
return
oss
.
str
();
}
bool
Plan
::
validate
(
const
PlanState
::
Ptr
&
state
)
const
{
PlanState
::
Ptr
last
=
state
;
for
(
std
::
size_t
step
=
cursor_
;
step
<
ops_
.
size
();
++
step
)
{
const
Operator
&
op
=
ops_
[
step
];
if
(
op
.
check_precondition
(
last
))
last
=
op
(
last
);
else
return
false
;
}
return
(
*
problem_
.
goal
)(
*
last
);
}
// StdLogger methods
const
Operator
&
Plan
::
next_action
()
void
StdLogger
::
log
(
const
std
::
string
&
msg
,
Logger
::
Level
level
)
const
{
if
(
cursor_
==
ops_
.
size
()
)
switch
(
level
)
{
throw
ImaginePlannerException
(
"Cursor is already at the end"
);
case
Logger
::
INFO
:
std
::
cout
<<
"\e[34m"
;
break
;
case
Logger
::
WARNING
:
std
::
cout
<<
"\e[33m"
;
break
;
case
Logger
::
ERROR
:
std
::
cout
<<
"\e[31m"
;
break
;
}
return
ops_
[
cursor_
++
]
;
std
::
cout
<<
msg
<<
"\e[0m"
<<
std
::
endl
;
}
...
...
@@ -45,15 +44,80 @@ const Operator& Plan::next_action()
Planner
::
Result
Planner
::
search
(
const
Problem
&
problem
)
{
start_
=
std
::
clock
();
do_search
(
problem
);
if
((
*
problem
.
goal
)(
*
problem
.
start
))
{
/* take care of the case in which the goal is already satisfied */
result_
=
FOUND
;
plan_
=
Plan
();
}
else
do_search
(
problem
);
stats_
[
"elapsed"
]
=
elapsed
();
if
(
result_
==
FOUND
)
msg_
=
"found"
;
else
if
(
result_
==
UNSOLVABLE
)
msg_
=
"unsolvable"
;
return
result_
;
}
void
Planner
::
reset
()
{
plan_
=
Plan
();
stats_
.
clear
();
result_
=
NOT_STARTED
;
msg_
.
clear
();
}
bool
Planner
::
get_parameter
(
const
Parameters
&
params
,
const
std
::
string
&
key
,
bool
def
)
{
auto
it
=
params
.
find
(
key
);
bool
ret
=
def
;
if
(
it
!=
params
.
end
())
{
std
::
string
value
=
it
->
second
;
std
::
transform
(
value
.
begin
(),
value
.
end
(),
value
.
begin
(),
::
tolower
);
ret
=
value
==
"true"
or
value
==
"1"
;
}
return
ret
;
}
int
Planner
::
get_parameter
(
const
Parameters
&
params
,
const
std
::
string
&
key
,
int
def
)
{
auto
it
=
params
.
find
(
key
);
int
ret
=
def
;
if
(
it
!=
params
.
end
())
ret
=
std
::
stoi
(
it
->
second
);
return
ret
;
}
double
Planner
::
get_parameter
(
const
Parameters
&
params
,
const
std
::
string
&
key
,
double
def
)
{
auto
it
=
params
.
find
(
key
);
int
ret
=
def
;
if
(
it
!=
params
.
end
())
ret
=
std
::
stod
(
it
->
second
);
return
ret
;
}
std
::
string
Planner
::
get_parameter
(
const
Parameters
&
params
,
const
std
::
string
&
key
,
const
std
::
string
&
def
)
{
auto
it
=
params
.
find
(
key
);
return
it
==
params
.
end
()
?
def
:
it
->
second
;
}
double
Planner
::
elapsed
()
const
{
return
(
std
::
clock
()
-
start_
)
/
(
double
)
CLOCKS_PER_SEC
;
}
void
Planner
::
log
(
const
std
::
string
&
msg
,
Logger
::
Level
level
)
const
{
if
(
logger_
)
{
std
::
string
timestamp
=
std
::
string
(
"["
)
+
std
::
to_string
(
elapsed
()
*
1000
)
+
"ms] "
;
logger_
->
log
(
timestamp
+
msg
,
level
);
}
}
}
src/imagine-planner.h
View file @
eb54b4f4
...
...
@@ -5,7 +5,12 @@
#include
<algorithm>
#include
<ctime>
#include
<utility>
#include
<sstream>
#define PLANNER_LOG(stream, level) {\
std::ostringstream oss; oss << stream;\
this->log(oss.str(), imagine_planner::Logger::level);\
}
namespace
imagine_planner
...
...
@@ -28,13 +33,15 @@ class Plan : public Stringifiable
{
public:
typedef
std
::
vector
<
Operator
>
OperatorV
;
typedef
std
::
vector
<
PlanState
::
Ptr
>
StateV
;
typedef
std
::
shared_ptr
<
const
Plan
>
Ptr
;
template
<
class
Tree
>
static
Plan
reconstruct_path
(
const
Problem
&
problem
,
const
Tree
&
tree
,
PlanState
::
Ptr
endstate
)
static
Plan
reconstruct_path
(
const
Tree
&
tree
,
PlanState
::
Ptr
endstate
)
{
std
::
vector
<
Operator
>
ops
;
std
::
vector
<
PlanState
::
Ptr
>
states
{
endstate
};
Operator
V
ops
;
StateV
states
{
endstate
};
auto
preceding
=
tree
.
find
(
endstate
)
->
second
;
while
(
preceding
.
first
)
{
...
...
@@ -44,57 +51,101 @@ class Plan : public Stringifiable
}
std
::
reverse
(
ops
.
begin
(),
ops
.
end
());
std
::
reverse
(
states
.
begin
(),
states
.
end
());
return
Plan
(
problem
,
ops
,
states
);
return
Plan
(
ops
,
states
);
}
Plan
(
const
Problem
&
problem
=
{},
const
std
::
vector
<
Operator
>&
ops
=
{},
const
std
::
vector
<
PlanState
::
Ptr
>&
states
=
{})
:
problem_
(
problem
),
ops_
(
ops
),
states_
(
states
),
cursor_
(
0
)
{}
Plan
()
{}
virtual
std
::
string
to_str
()
const
override
;
Plan
(
const
OperatorV
&
ops
,
const
StateV
&
states
)
:
ops_
(
ops
),
states_
(
states
)
{}
bool
validate
(
const
PlanState
::
P
tr
&
state
)
const
;
virtual
std
::
s
tr
ing
to_str
()
const
override
;
bool
completed
()
const
{
return
cursor_
==
ops_
.
size
()
;
}
const
Operator
&
operator
[](
std
::
size_t
idx
)
const
{
return
ops_
[
idx
]
;
}
const
Op
erator
&
next_actio
n
();
OperatorV
::
const
_it
erator
begin
()
const
{
return
ops_
.
begi
n
();
}
void
reset
()
{
cursor_
=
0
;
}
OperatorV
::
const_iterator
end
()
const
{
return
ops_
.
end
()
;
}
const
std
::
vector
<
Operator
>&
operations
()
const
{
return
ops_
;
}
std
::
size_t
size
()
const
{
return
ops_
.
size
()
;
}
const
std
::
vector
<
PlanState
::
Ptr
>&
states
()
const
{
return
states_
;
}
const
StateV
&
get_
states
()
const
{
return
states_
;
}
private:
Problem
problem_
;
std
::
vector
<
Operator
>
ops_
;
std
::
vector
<
PlanState
::
Ptr
>
states_
;
std
::
size_t
cursor_
;
OperatorV
ops_
;
StateV
states_
;
};
class
Logger
{
public:
typedef
std
::
unique_ptr
<
const
Logger
>
Ptr
;
enum
Level
{
INFO
,
WARNING
,
ERROR
};
virtual
void
log
(
const
std
::
string
&
msg
,
Level
level
)
const
=
0
;
virtual
~
Logger
()
{}
};
class
StdLogger
:
public
Logger
{
public:
void
log
(
const
std
::
string
&
msg
,
Logger
::
Level
level
=
INFO
)
const
override
;
};
class
Planner
{
public:
enum
Result
{
FOUND
,
UNSOLVABLE
,
NOT_FOUND
};
enum
Result
{
FOUND
,
UNSOLVABLE
,
NOT_FOUND
,
NOT_STARTED
};
typedef
std
::
map
<
std
::
string
,
double
>
Statistics
;
typedef
std
::
map
<
std
::
string
,
std
::
string
>
Parameters
;
Planner
()
:
result_
(
NOT_STARTED
)
{}
void
set_logger
(
Logger
::
Ptr
&&
logger
)
{
logger_
=
std
::
move
(
logger
);
}
virtual
void
set_parameters
(
const
Parameters
&
params
)
=
0
;
Result
search
(
const
Problem
&
problem
);
const
Statistics
&
get_stats
()
const
{
return
stats_
;
}
Result
get_result
()
const
{
return
result_
;
}
const
std
::
string
&
get_message
()
const
{
return
msg_
;
}
const
Plan
&
get_plan
()
const
{
return
plan_
;
}
virtual
~
Planner
()
{};
virtual
void
reset
();
protected:
static
bool
get_parameter
(
const
Parameters
&
params
,
const
std
::
string
&
key
,
bool
def
);
static
int
get_parameter
(
const
Parameters
&
params
,
const
std
::
string
&
key
,
int
def
);
static
double
get_parameter
(
const
Parameters
&
params
,
const
std
::
string
&
key
,
double
def
);
std
::
string
get_parameter
(
const
Parameters
&
params
,
const
std
::
string
&
key
,
const
std
::
string
&
def
);
virtual
void
do_search
(
const
Problem
&
problem
)
=
0
;
double
elapsed
()
const
;
void
log
(
const
std
::
string
&
msg
,
Logger
::
Level
level
=
Logger
::
INFO
)
const
;
Plan
plan_
;
std
::
map
<
std
::
string
,
double
>
stats_
;
Result
result_
;
...
...
@@ -103,6 +154,8 @@ class Planner
private:
std
::
clock_t
start_
;
Logger
::
Ptr
logger_
;
};
}
/* end of imagine_planner namespace */
...
...
src/types.h
View file @
eb54b4f4
...
...
@@ -348,7 +348,7 @@ class PlanState : public Stringifiable,
return
std
::
make_shared
<
PlanState
>
(
predicates
);
}
PlanState
(
const
Container
&
predicates
)
PlanState
(
const
Container
&
predicates
=
{}
)
:
predicates_
(
predicates
),
hash_cached_
(
false
)
{}
template
<
typename
InputIterator
>
...
...
@@ -390,6 +390,8 @@ class PlanState : public Stringifiable,
CIter
end
()
const
{
return
predicates_
.
end
();
}