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 7, 2024
1 parent e7451b6 commit c86aa99
Show file tree
Hide file tree
Showing 4 changed files with 172 additions and 32 deletions.
14 changes: 14 additions & 0 deletions include/dlplan/utils/hash.h
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,20 @@ inline std::size_t hash_set(const std::set<T, C>& set)
return aggregated_hash;
}

template<class Container>
inline std::size_t hash_container(const Container& container)
{
using T = typename Container::value_type;
const auto hash_function = std::hash<T>();
std::size_t aggregated_hash = 0;
for (const auto& item : container)
{
const auto item_hash = hash_function(item);
hash_combine(aggregated_hash, item_hash);
}
return aggregated_hash;
}

}

namespace std {
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.20"
__version__ = "0.3.21"
HERE = Path(__file__).resolve().parent


Expand Down
178 changes: 152 additions & 26 deletions src/novelty/tuple_graph_builder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,50 @@ std::ostream& operator<<(
return os;
}

/// @brief Prints a vector to the output stream.
template<typename T>
std::ostream& operator<<(
std::ostream& os,
const std::unordered_set<T>& set)
{
os << "{";
size_t i = 0;
for (const auto element : set)
{
if (i != 0)
{
os << ", ";
}
os << element;
++i;
}
os << "}";

return os;
}

/// @brief Prints a vector to the output stream.
template<typename T>
std::ostream& operator<<(
std::ostream& os,
const std::set<T>& set)
{
os << "{";
size_t i = 0;
for (const auto element : set)
{
if (i != 0)
{
os << ", ";
}
os << element;
++i;
}
os << "}";

return os;
}

StateIndices TupleGraphBuilder::compute_state_layer(
const StateIndices& current_layer,
StateIndicesSet& visited_state_indices)
Expand Down Expand Up @@ -101,6 +145,7 @@ TupleGraphBuilder::extend_states(TupleIndex cur_node_index) const {
return extended;
}

/*
void TupleGraphBuilder::extend_nodes(
const TupleIndicesSet& curr_novel_tuple_indices,
TupleNodeIndex cur_node_index,
Expand All @@ -109,6 +154,7 @@ void TupleGraphBuilder::extend_nodes(
std::vector<TupleNode> curr_tuple_node_layer;
auto extended = extend_states(cur_node_index);
TupleIndices extended_tuple_indices;
for (const auto& pair : extended)
{
const auto succ_tuple_index = pair.first;
Expand All @@ -117,22 +163,24 @@ void TupleGraphBuilder::extend_nodes(
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();
auto find = novel_tuple_index_to_node.find(succ_tuple_index);
if (find == novel_tuple_index_to_node.end())
{
auto tuple_node = TupleNode(
succ_node_index,
-1, // unregistered
succ_tuple_index,
m_novel_tuple_index_to_state_indices.at(succ_tuple_index));
next_tuple_node_layer.push_back(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);
novel_tuple_index_to_node.emplace(succ_tuple_index, succ_node_index);
m_nodes[cur_node_index].add_successor(succ_node_index);
m_nodes[succ_node_index].add_predecessor(cur_node_index);
}
}
else
{
Expand All @@ -143,23 +191,108 @@ void TupleGraphBuilder::extend_nodes(
}
}
}
*/



struct SetHash {
size_t operator()(const StateIndicesSet& set) const {
return hash_container(set);
}
};


struct SetEqual {
bool operator()(const StateIndicesSet& lhs, const StateIndicesSet& rhs) const {
return lhs == rhs;
}
};


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;

TupleIndicesSet curr_extended_tuple_indices;
std::unordered_map<TupleIndex, TupleNodeIndicesSet> predecessor_tuple_nodes;
for (auto& cur_node_index : prev_tuple_layer)
{
extend_nodes(curr_novel_tuple_indices, cur_node_index, novel_tuple_index_to_node);
auto extended = extend_states(cur_node_index);

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

// Check whether all optimal plans for cur_node_index can be extended into optimal plans for succ_tuple_index
if (curr_novel_tuple_indices.count(succ_tuple_index)
&& cur_node_extended_states.size() == m_nodes[cur_node_index].get_state_indices().size())
{
curr_extended_tuple_indices.insert(succ_tuple_index);

predecessor_tuple_nodes[succ_tuple_index].insert(cur_node_index);
}
}
}
//std::cout << "curr_extended_tuple_indices: " << curr_extended_tuple_indices << std::endl;

// Compute ordering "supset" t > t' iff S*(t) supset S*(t')
std::unordered_map<TupleIndex, TupleIndicesSet> supset_subgoals;
for (const auto tuple_index_1 : curr_extended_tuple_indices)
{
const auto& subgoals_1 = m_novel_tuple_index_to_state_indices.at(tuple_index_1);

// create empty entry
supset_subgoals[tuple_index_1] = TupleIndicesSet{};

for (const auto tuple_index_2 : curr_extended_tuple_indices)
{
const auto& subgoals_2 = m_novel_tuple_index_to_state_indices.at(tuple_index_2);
//std::cout << "tuple_index_1: " << tuple_index_1 << " subgoals_1: " << subgoals_1 << " tuple_index_2: " << tuple_index_2 << " subgoals_2: " << subgoals_2 << std::endl;
if ((subgoals_1.size() != subgoals_2.size())
&& std::includes(
subgoals_1.begin(), subgoals_1.end(),
subgoals_2.begin(), subgoals_2.end()))
{
supset_subgoals[tuple_index_1].insert(tuple_index_2);
//std::cout << tuple_index_1 << " > " << tuple_index_2 << std::endl;
}
}
}

for (auto& pair : novel_tuple_index_to_node)
// From each minimal element according to "supset" pick one representative
std::unordered_map<StateIndicesSet, TupleIndex, SetHash, SetEqual> curr_tuple_indices;
for (const auto& [tuple_index, supsets] : supset_subgoals)
{
curr_tuple_layer.push_back(pair.second);
if (supsets.empty())
{
const auto& subgoals = m_novel_tuple_index_to_state_indices.at(tuple_index);

if (!curr_tuple_indices.count(subgoals))
{
curr_tuple_indices.emplace(subgoals, tuple_index);
}
}
}

// Create nodes
TupleNodeIndices curr_tuple_layer;
for (const auto& [_, tuple_index] : curr_tuple_indices)
{
//std::cout << "tuple_index: " << tuple_index << std::endl;
auto node_index = m_nodes.size();
const auto& subgoals = m_novel_tuple_index_to_state_indices.at(tuple_index);
m_nodes.push_back(TupleNode(node_index, tuple_index, subgoals));
curr_tuple_layer.push_back(node_index);

for (const auto predecessor_node_index : predecessor_tuple_nodes[tuple_index])
{
m_nodes[predecessor_node_index].add_successor(node_index);
m_nodes[node_index].add_predecessor(predecessor_node_index);
}
}

return curr_tuple_layer;
}

Expand Down Expand Up @@ -208,38 +341,31 @@ void TupleGraphBuilder::build_width_equal_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;
TupleNodeIndex node_index = m_nodes.size();
TupleIndex tuple_index = m_novelty_base->atom_indices_to_tuple_index({});
TupleNode tuple_node = TupleNode(node_index, tuple_index, StateIndicesSet{m_root_state_index});
m_nodes.push_back(tuple_node);
m_node_indices_by_distance.push_back(TupleNodeIndices{node_index});
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)
{
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))
{
curr_tuple_node_layer.push_back(tuple_node);
m_nodes.push_back(tuple_node);
initial_tuple_layer.push_back(node_index);
}
}
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)
{
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);
//std::cout << "curr_state_layer: " << curr_state_layer << std::endl;
auto novel_tuple_indices = compute_novel_tuple_indices_layer(curr_state_layer);
//std::cout << "novel_tuple_indices: " << novel_tuple_indices << std::endl;

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

if (curr_tuple_layer.empty())
{
Expand Down
10 changes: 5 additions & 5 deletions tests/novelty/gripper/gripper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -38,11 +38,11 @@ TEST(DLPTests, NoveltyGripperTest) {

EXPECT_EQ(TupleGraph(novelty_base_2, state_space2, 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, 5, 8, 12, 15]),\n TupleNode(index=1, tuple_index=54, state_indices={1}, predecessors=[0], successors=[]),\n TupleNode(index=2, tuple_index=79, state_indices={16}, predecessors=[3, 7], successors=[]),\n TupleNode(index=3, tuple_index=82, state_indices={12}, predecessors=[6], successors=[2]),\n TupleNode(index=4, tuple_index=93, state_indices={6}, predecessors=[8], successors=[7]),\n TupleNode(index=5, tuple_index=104, state_indices={4}, predecessors=[0], successors=[6, 14]),\n TupleNode(index=6, tuple_index=106, state_indices={10}, predecessors=[5], successors=[3, 7]),\n TupleNode(index=7, tuple_index=123, state_indices={12}, predecessors=[4, 6], successors=[2]),\n TupleNode(index=8, tuple_index=124, state_indices={2}, predecessors=[0], successors=[4, 17]),\n TupleNode(index=9, tuple_index=131, state_indices={19}, predecessors=[10, 11], successors=[]),\n TupleNode(index=10, tuple_index=134, state_indices={14}, predecessors=[13], successors=[9]),\n TupleNode(index=11, tuple_index=135, state_indices={14}, predecessors=[13, 16], successors=[9]),\n TupleNode(index=12, tuple_index=143, state_indices={3}, predecessors=[0], successors=[13, 14]),\n TupleNode(index=13, tuple_index=145, state_indices={8}, predecessors=[12], successors=[10, 11]),\n TupleNode(index=14, tuple_index=151, state_indices={9}, predecessors=[5, 12], successors=[]),\n TupleNode(index=15, tuple_index=156, state_indices={5}, predecessors=[0], successors=[16, 17]),\n TupleNode(index=16, tuple_index=158, state_indices={11}, predecessors=[15], successors=[11]),\n TupleNode(index=17, tuple_index=163, state_indices={7}, predecessors=[8, 15], successors=[])\n ],\n node_indices_by_distance=[\n [0],\n [1, 5, 8, 12, 15],\n [4, 6, 13, 14, 16, 17],\n [3, 7, 10, 11],\n [2, 9]\n ],\n state_indices_by_distance=[\n [0],\n [1, 2, 3, 4, 5],\n [6, 7, 8, 9, 10, 11],\n [12, 13, 14, 15],\n [16, 17, 18, 19, 20, 21]\n ]\n)");

//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;
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;

}

Expand Down

0 comments on commit c86aa99

Please sign in to comment.