Skip to content

Commit

Permalink
work on tuple graph
Browse files Browse the repository at this point in the history
  • Loading branch information
drexlerd committed Mar 6, 2024
1 parent 07562b6 commit d6e993b
Show file tree
Hide file tree
Showing 6 changed files with 149 additions and 45 deletions.
2 changes: 2 additions & 0 deletions include/dlplan/novelty.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,11 +27,13 @@ using AtomIndices = std::vector<AtomIndex>;

using TupleIndex = int;
using TupleIndices = std::vector<TupleIndex>;
using TupleIndicesSet = std::unordered_set<TupleIndex>;

using StateIndicesSet = std::set<int>;

using TupleNodeIndex = int;
using TupleNodeIndices = std::vector<TupleNodeIndex>;
using TupleNodeIndicesSet = std::unordered_set<TupleNodeIndex>;
using TupleNodes = std::vector<TupleNode>;

/// @brief Implements a perfect hash function between tuple index and atom indices.
Expand Down
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
from setuptools import setup, find_packages, Extension
from setuptools.command.build_ext import build_ext

__version__ = "0.3.19"
__version__ = "0.3.20"
HERE = Path(__file__).resolve().parent


Expand Down
168 changes: 125 additions & 43 deletions src/novelty/tuple_graph_builder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,18 +4,44 @@


namespace dlplan::novelty {
/// @brief Prints a vector to the output stream.
template<typename T>
std::ostream& operator<<(
std::ostream& os,
const std::vector<T>& vec)
{
os << "[";
for (size_t i = 0; i < vec.size(); ++i)
{
if (i != 0)
{
os << ", ";
}
os << vec[i];
}
os << "]";

return os;
}

StateIndices TupleGraphBuilder::compute_state_layer(
const StateIndices& current_layer,
StateIndicesSet &visited_state_indices) {
StateIndicesSet& visited_state_indices)
{
std::unordered_set<StateIndex> layer_set;
const auto& successors = m_state_space->get_forward_successor_state_indices();
for (const auto source_index : current_layer) {

for (const auto source_index : current_layer)
{
assert(visited_state_indices.count(source_index));
const auto it = successors.find(source_index);
if (it != successors.end()) {
for (const auto target_index : it->second) {
if (!visited_state_indices.count(target_index)) {

if (it != successors.end())
{
for (const auto target_index : it->second)
{
if (!visited_state_indices.count(target_index))
{
visited_state_indices.insert(target_index);
layer_set.insert(target_index);
}
Expand All @@ -25,34 +51,47 @@ StateIndices TupleGraphBuilder::compute_state_layer(
return StateIndices(layer_set.begin(), layer_set.end());
}

TupleIndices TupleGraphBuilder::compute_novel_tuple_indices_layer(const StateIndices& curr_state_layer) {
std::unordered_set<TupleIndex> novel_tuples_set;
for (const auto state_index : curr_state_layer) {
TupleIndicesSet TupleGraphBuilder::compute_novel_tuple_indices_layer(const StateIndices& curr_state_layer)
{
TupleIndicesSet novel_tuples_set;

for (const auto state_index : curr_state_layer)
{
const TupleIndices state_novel_tuples = m_novelty_table.compute_novel_tuple_indices(
{},
m_state_space->get_states().at(state_index).get_atom_indices());
novel_tuples_set.insert(state_novel_tuples.begin(), state_novel_tuples.end());
m_state_index_to_novel_tuple_indices.emplace(state_index, state_novel_tuples);
for (const auto tuple_index : state_novel_tuples) {

for (const auto tuple_index : state_novel_tuples)
{
m_novel_tuple_index_to_state_indices[tuple_index].insert(state_index);
}
}
TupleIndices novel_tuples = TupleIndices(novel_tuples_set.begin(), novel_tuples_set.end());
m_novelty_table.insert_tuple_indices(novel_tuples, false);
return novel_tuples;
return novel_tuples_set;
}

std::unordered_map<TupleIndex, StateIndicesSet>
TupleGraphBuilder::extend_states(TupleIndex cur_node_index) const {
std::unordered_map<TupleIndex, StateIndicesSet> extended;
const auto& successors = m_state_space->get_forward_successor_state_indices();
for (const auto source_index : m_nodes[cur_node_index].get_state_indices()) {

for (const auto source_index : m_nodes[cur_node_index].get_state_indices())
{
const auto it = successors.find(source_index);
if (it != successors.end()) {
for (const auto target_index : it->second) {

if (it != successors.end())
{
for (const auto target_index : it->second)
{
const auto it = m_state_index_to_novel_tuple_indices.find(target_index);
if (it != m_state_index_to_novel_tuple_indices.end()) {
for (const auto target_tuple_index : it->second) {

if (it != m_state_index_to_novel_tuple_indices.end())
{
for (const auto target_tuple_index : it->second)
{
extended[target_tuple_index].insert(source_index);
}
}
Expand All @@ -63,17 +102,26 @@ TupleGraphBuilder::extend_states(TupleIndex cur_node_index) const {
}

void TupleGraphBuilder::extend_nodes(
const TupleIndicesSet& curr_novel_tuple_indices,
TupleNodeIndex cur_node_index,
std::unordered_map<TupleIndex, TupleNodeIndex> &novel_tuple_index_to_node)
{
std::vector<TupleNode> curr_tuple_node_layer;
auto extended = extend_states(cur_node_index);
for (const auto& pair : extended) {
if (pair.second.size() == m_nodes[cur_node_index].get_state_indices().size()) {

for (const auto& pair : extended)
{
const auto succ_tuple_index = pair.first;
const auto& cur_node_extended_states = pair.second;

if (curr_novel_tuple_indices.count(succ_tuple_index)
&& cur_node_extended_states.size() == m_nodes[cur_node_index].get_state_indices().size())
{
int succ_node_index = m_nodes.size();
TupleIndex succ_tuple_index = pair.first;
auto find = novel_tuple_index_to_node.find(succ_tuple_index);
if (find == novel_tuple_index_to_node.end()) {

if (find == novel_tuple_index_to_node.end())
{
auto tuple_node = TupleNode(
succ_node_index,
succ_tuple_index,
Expand All @@ -85,7 +133,9 @@ void TupleGraphBuilder::extend_nodes(
m_nodes[cur_node_index].add_successor(succ_node_index);
m_nodes[succ_node_index].add_predecessor(cur_node_index);
}
} else {
}
else
{
succ_node_index = find->second;
m_nodes[cur_node_index].add_successor(succ_node_index);
m_nodes[succ_node_index].add_predecessor(cur_node_index);
Expand All @@ -94,39 +144,54 @@ void TupleGraphBuilder::extend_nodes(
}
}

TupleNodeIndices TupleGraphBuilder::compute_nodes_layer(TupleNodeIndices& prev_tuple_layer) {
TupleNodeIndices TupleGraphBuilder::compute_nodes_layer(
const TupleIndicesSet& curr_novel_tuple_indices,
TupleNodeIndices& prev_tuple_layer)
{
TupleNodeIndices curr_tuple_layer;
std::unordered_map<TupleIndex, TupleNodeIndex> novel_tuple_index_to_node;
for (auto& cur_node_index : prev_tuple_layer) {
extend_nodes(cur_node_index, novel_tuple_index_to_node);

for (auto& cur_node_index : prev_tuple_layer)
{
extend_nodes(curr_novel_tuple_indices, cur_node_index, novel_tuple_index_to_node);
}
for (auto& pair : novel_tuple_index_to_node) {

for (auto& pair : novel_tuple_index_to_node)
{
curr_tuple_layer.push_back(pair.second);
}
return curr_tuple_layer;
}

bool TupleGraphBuilder::test_prune(const std::vector<TupleNode>& tuple_node_layer, const TupleNode& tuple_node) {
for (const auto& curr_tuple_node : tuple_node_layer) {
bool TupleGraphBuilder::test_prune(const std::vector<TupleNode>& tuple_node_layer, const TupleNode& tuple_node)
{
for (const auto& curr_tuple_node : tuple_node_layer)
{
if (std::includes(
curr_tuple_node.get_state_indices().begin(), curr_tuple_node.get_state_indices().end(),
tuple_node.get_state_indices().begin(), tuple_node.get_state_indices().end())) {
tuple_node.get_state_indices().begin(), tuple_node.get_state_indices().end()))
{
return true;
}
}
return false;
}

void TupleGraphBuilder::build_width_equal_0_tuple_graph() {
void TupleGraphBuilder::build_width_equal_0_tuple_graph()
{
TupleNodeIndex initial_node_index = m_nodes.size();
m_node_indices_by_distance.push_back({initial_node_index});
m_nodes.push_back({TupleNode(initial_node_index, initial_node_index, {m_root_state_index})});
m_state_indices_by_distance.push_back({m_root_state_index});
const auto& it = m_state_space->get_forward_successor_state_indices().find(m_root_state_index);
if (it != m_state_space->get_forward_successor_state_indices().end()) {

if (it != m_state_space->get_forward_successor_state_indices().end())
{
TupleNodeIndices curr_tuple_layer;
StateIndices curr_state_layer;
for (const auto& target_index : it->second) {

for (const auto& target_index : it->second)
{
TupleNodeIndex node_index = m_nodes.size();
curr_tuple_layer.push_back(node_index);
auto tuple_node = TupleNode(node_index, node_index, {target_index});
Expand All @@ -137,21 +202,24 @@ void TupleGraphBuilder::build_width_equal_0_tuple_graph() {
}
m_node_indices_by_distance.push_back(curr_tuple_layer);
m_state_indices_by_distance.push_back(curr_state_layer);

}
}

void TupleGraphBuilder::build_width_greater_0_tuple_graph() {
void TupleGraphBuilder::build_width_greater_0_tuple_graph()
{
StateIndicesSet visited_state_indices;
// 1. Initialize root state with distance = 0
m_state_indices_by_distance.push_back(StateIndices{m_root_state_index});
TupleNodeIndices initial_tuple_layer;
TupleIndices tuple_indices = m_novelty_table.compute_novel_tuple_indices(m_state_space->get_states().at(m_root_state_index).get_atom_indices());
std::vector<TupleNode> curr_tuple_node_layer;
for (const auto tuple_index : tuple_indices) {

for (const auto tuple_index : tuple_indices)
{
int node_index = m_nodes.size();
auto tuple_node = TupleNode(node_index, tuple_index, StateIndicesSet{m_root_state_index});
if (!m_enable_pruning || !test_prune(curr_tuple_node_layer, tuple_node)) {
if (!m_enable_pruning || !test_prune(curr_tuple_node_layer, tuple_node))
{
curr_tuple_node_layer.push_back(tuple_node);
m_nodes.push_back(tuple_node);
initial_tuple_layer.push_back(node_index);
Expand All @@ -160,17 +228,24 @@ void TupleGraphBuilder::build_width_greater_0_tuple_graph() {
m_node_indices_by_distance.push_back(std::move(initial_tuple_layer));
m_novelty_table.insert_tuple_indices(tuple_indices, false);
visited_state_indices.insert(m_root_state_index);

// 2. Iterate distances > 0
for (int distance = 1; ; ++distance) {
for (int distance = 1; ; ++distance)
{
StateIndices curr_state_layer = compute_state_layer(m_state_indices_by_distance[distance-1], visited_state_indices);
auto novel_tuples = compute_novel_tuple_indices_layer(curr_state_layer);
if (novel_tuples.empty()) {

if (novel_tuples.empty())
{
break;
}
TupleNodeIndices curr_tuple_layer = compute_nodes_layer(m_node_indices_by_distance[distance-1]);
if (curr_tuple_layer.empty()) {
TupleNodeIndices curr_tuple_layer = compute_nodes_layer(novel_tuples, m_node_indices_by_distance[distance-1]);

if (curr_tuple_layer.empty())
{
break;
}

m_node_indices_by_distance.push_back(std::move(curr_tuple_layer));
m_state_indices_by_distance.push_back(std::move(curr_state_layer));
}
Expand All @@ -185,21 +260,28 @@ TupleGraphBuilder::TupleGraphBuilder(
m_state_space(state_space),
m_root_state_index(root_state),
m_enable_pruning(enable_pruning),
m_novelty_table(novelty_base) {
if (!m_novelty_base) {
m_novelty_table(novelty_base)
{
if (!m_novelty_base)
{
throw std::runtime_error("TupleGraphBuilder::TupleGraphBuilder - novelty_base is nullptr.");
}
if (!m_novelty_base) {

if (!m_novelty_base)
{
throw std::runtime_error("TupleGraphBuilder::TupleGraphBuilder - state_space is nullptr.");
}
if (m_novelty_base->get_arity() == 0) {

if (m_novelty_base->get_arity() == 0)
{
build_width_equal_0_tuple_graph();
} else {
build_width_greater_0_tuple_graph();
}
}

TupleGraphBuilderResult TupleGraphBuilder::get_result() {
TupleGraphBuilderResult TupleGraphBuilder::get_result()
{
return TupleGraphBuilderResult{
std::move(m_nodes),
std::move(m_node_indices_by_distance),
Expand Down
4 changes: 3 additions & 1 deletion src/novelty/tuple_graph_builder.h
Original file line number Diff line number Diff line change
Expand Up @@ -45,13 +45,14 @@ class TupleGraphBuilder {

/// @brief Computes all tuples that are novel in any state of the given layer.
/// @param current_state_layer
TupleIndices
TupleIndicesSet
compute_novel_tuple_indices_layer(
const StateIndices& curr_state_layer);

/// @brief Computes all nodes in next layer, given the ones in the current layer.
TupleNodeIndices
compute_nodes_layer(
const TupleIndicesSet& curr_novel_tuple_indices,
TupleNodeIndices& prev_tuple_layer);

/// @brief Computes all successor tuples in next layer for the tuple in current layer
Expand All @@ -63,6 +64,7 @@ class TupleGraphBuilder {
/// in current layer with cur_node_index.
void
extend_nodes(
const TupleIndicesSet& curr_novel_tuple_indices,
TupleNodeIndex cur_node_index,
std::unordered_map<TupleIndex, TupleNodeIndex> &novel_tuple_index_to_node);

Expand Down
3 changes: 3 additions & 0 deletions tests/novelty/gripper/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,9 @@ add_custom_target(novelty_gripper_domain ALL
COMMAND ${CMAKE_COMMAND} -E copy "${CMAKE_CURRENT_SOURCE_DIR}/domain.pddl" "${CMAKE_BINARY_DIR}/tests/novelty/gripper/domain.pddl")
add_custom_target(novelty_gripper_instance ALL
COMMAND ${CMAKE_COMMAND} -E copy "${CMAKE_CURRENT_SOURCE_DIR}/p-1-0.pddl" "${CMAKE_BINARY_DIR}/tests/novelty/gripper/p-1-0.pddl")
add_custom_target(novelty_gripper_instance2 ALL
COMMAND ${CMAKE_COMMAND} -E copy "${CMAKE_CURRENT_SOURCE_DIR}/p-2-0.pddl" "${CMAKE_BINARY_DIR}/tests/novelty/gripper/p-2-0.pddl")


target_link_libraries(novelty_gripper_tests
PRIVATE
Expand Down
15 changes: 15 additions & 0 deletions tests/novelty/gripper/gripper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
#include "../../../include/dlplan/novelty.h"

#include <iostream>
#include <fstream>

using namespace dlplan::core;
using namespace dlplan::state_space;
Expand All @@ -25,8 +26,22 @@ TEST(DLPTests, NoveltyGripperTest) {
auto novelty_base_1 = std::make_shared<NoveltyBase>(
state_space->get_instance_info()->get_atoms().size(),
1);

EXPECT_EQ(TupleGraph(novelty_base_1, state_space, 0, false).compute_repr(), "TupleGraph(\n root_state_index=0,\n tuple_nodes=[ TupleNode(index=0, tuple_index=0, state_indices={0}, predecessors=[], successors=[2, 6, 7]),\n TupleNode(index=1, tuple_index=1, state_indices={0}, predecessors=[], successors=[2, 6, 7]),\n TupleNode(index=2, tuple_index=2, state_indices={1}, predecessors=[0, 1, 3, 4, 5], successors=[]),\n TupleNode(index=3, tuple_index=3, state_indices={0}, predecessors=[], successors=[2, 6, 7]),\n TupleNode(index=4, tuple_index=4, state_indices={0}, predecessors=[], successors=[2, 6, 7]),\n TupleNode(index=5, tuple_index=5, state_indices={0}, predecessors=[], successors=[2, 6, 7]),\n TupleNode(index=6, tuple_index=7, state_indices={2}, predecessors=[0, 1, 3, 4, 5], successors=[]),\n TupleNode(index=7, tuple_index=8, state_indices={3}, predecessors=[0, 1, 3, 4, 5], successors=[])\n ],\n node_indices_by_distance=[\n [0, 1, 3, 4, 5],\n [2, 6, 7]\n ],\n state_indices_by_distance=[\n [0],\n [1, 2, 3]\n ]\n)");
EXPECT_EQ(TupleGraph(novelty_base_1, state_space, 0, true).compute_repr(), "TupleGraph(\n root_state_index=0,\n tuple_nodes=[ TupleNode(index=0, tuple_index=0, state_indices={0}, predecessors=[], successors=[1, 2, 3]),\n TupleNode(index=1, tuple_index=2, state_indices={1}, predecessors=[0], successors=[]),\n TupleNode(index=2, tuple_index=7, state_indices={2}, predecessors=[0], successors=[]),\n TupleNode(index=3, tuple_index=8, state_indices={3}, predecessors=[0], successors=[])\n ],\n node_indices_by_distance=[\n [0],\n [1, 2, 3]\n ],\n state_indices_by_distance=[\n [0],\n [1, 2, 3]\n ]\n)");

std::cout << std::endl;
auto result2 = generate_state_space("domain.pddl", "p-2-0.pddl");
auto state_space2 = result2.state_space;
auto novelty_base_2 = std::make_shared<NoveltyBase>(
state_space2->get_instance_info()->get_atoms().size(),
1);
std::ofstream file("out.dot");
const auto tg = TupleGraph(novelty_base_2, state_space2, 2, true);
file << tg.to_dot(1);
file.close();

std::cout << tg.compute_repr() << std::endl;
}

}

0 comments on commit d6e993b

Please sign in to comment.