dyng
|
A dynamic time expanded network. More...
#include <Net.hxx>
Data Structures | |
class | BaseInIterator |
Iterator over the incoming arcs of a base node. More... | |
class | BaseInList |
Wrapper to provide an iterator over the incoming arcs of a base node. More... | |
class | BaseOutIterator |
Iterator over the outgoing arcs of a base node. More... | |
class | BaseOutList |
Wrapper to provide an iterator over the outgoing arcs of a base node. More... | |
class | InIterator |
Iterator over the incoming arcs of a node. More... | |
class | InList |
Wrapper to provide an iterator over the incoming arcs of a node. More... | |
class | OutIterator |
Iterator over the outgoing arcs of a node. More... | |
class | OutList |
Wrapper to provide an iterator over the outgoing arcs of a node. More... | |
Public Types | |
enum | Result { Result::Solved =1, Result::Expanded =2 } |
Return states of the shortest path computation. More... | |
typedef index_type | Group |
Type of groups. | |
typedef index_type | BaseNode |
Type of base nodes. | |
typedef index_type | BaseArc |
Type of base arcs. | |
typedef index_type | Node |
Type of nodes. | |
typedef index_type | Arc |
Type of arcs. | |
typedef index_type | Time |
Type of time indices. | |
typedef index_type | RunTime |
Type of running times. | |
Public Member Functions | |
Net () | |
Constructor. More... | |
~Net () | |
Destructor. | |
Net (const Net &net)=delete | |
No copy constructor. | |
Net & | operator= (const Net &net)=delete |
No assignment operator. | |
Net (Net &&net) | |
Move constructor. | |
Net & | operator= (Net &&net) |
Move assignment operator. | |
Base graph functions | |
index_type | n_groups () const |
Return the number of groups in the base graph. More... | |
Group | add_group () |
Add one group to the base graph. More... | |
Group | add_groups (index_type ngroups) |
Add several groups to the base graph. More... | |
index_type | n_basenodes () const |
Return the number of base nodes. More... | |
BaseNode | add_basenode (Group group) |
Add a base node to the network. More... | |
Group | base_group (BaseNode bnode) const |
Returns the index of the group of a base node. More... | |
index_type | base_groupidx (BaseNode bnode) const |
Returns the number of the node in its group. More... | |
bool | base_waitnode (BaseNode bnode) const |
Returns true if the base node is a wait node. More... | |
BaseArc | base_firstout (BaseNode bnode) const |
Return first outgoing arc of a node in the base graph. More... | |
BaseArc | base_firstin (BaseNode bnode) const |
Return first incoming arc of a node in the base graph. More... | |
index_type | n_basearcs () const |
Return the number of base arcs. More... | |
BaseArc | add_basearc (BaseNode bsrc, BaseNode bsnk) |
Add an arc to the base graph. More... | |
BaseArc | base_arc (BaseNode bsrc, BaseNode bsnk) const |
Returns the id of a base arc. More... | |
void | add_runningtime (BaseArc arc, RunTime running_time) |
Add one possible running time to a base arc. More... | |
void | add_runningtimes (BaseArc arc, std::size_t ntimes, const RunTime running_times[]) |
Add several possible running times to a base arc. More... | |
void | add_runningtimes (BaseArc arc, const std::vector< RunTime > &running_times) |
BaseArc | base_nextout (BaseArc arc) const |
Return the next outgoing base arc. More... | |
BaseArc | base_nextin (BaseArc arc) const |
Return the next incoming base arc. More... | |
BaseNode | base_src (BaseArc arc) const |
Return the number of the source base node of a base arc. More... | |
BaseNode | base_snk (BaseArc arc) const |
Return the number of the sink base node of a base arc. More... | |
BaseOutList | base_outarcs (BaseNode bnode) const |
Return a list of outgoing arcs of a base node. | |
BaseInList | base_inarcs (BaseNode bnode) const |
Return a list of incoming arcs of a base node. | |
Time expansion functions | |
void | init () |
Initializes the time expansion. More... | |
Time | group_mintime (Group group) const |
Return the minimal possible time associated with a group. More... | |
Time | basenode_mintime (BaseNode bnode) const |
Return the minimal possible time associated with a basenode. More... | |
index_type | n_nodes () const |
Returns the number of nodes in the time expansion. More... | |
Node | node (BaseNode bnode, Time time) const |
Returns the id of a node in the time expansion. More... | |
BaseNode | basenode (Node node) const |
Returns the id of the base node associated with a node. More... | |
Time | time (Node node) const |
Returns the time index associated with a node in the time expansion. More... | |
Arc | firstout (Node node) const |
Returns the id of the first outgoing arc in the time expansion. More... | |
Arc | firstin (Node node) const |
Returns the id of the first incoming arc in the time expansion. More... | |
index_type | n_arcs () const |
Returns the number of arcs in the time expansion. More... | |
Arc | arc (Node src, Node snk) const |
Returns the id of an arc in the time expansion. More... | |
Arc | find_arc (BaseNode bsrc, Time srctime, BaseNode bsnk, Time snktime) const |
Returns the id of an arc in the time expansion. More... | |
bool | isactive (Arc arc) const |
Returns true iff the given arc is contained in the active subgraph. More... | |
Node | src (Arc arc) const |
Returns the id of the source node of an arc in the time expansion. More... | |
Node | snk (Arc arc) const |
Returns the id of the sink node of an arc in the time expansion. More... | |
Arc | nextout (Arc arc) const |
Returns the id of the next outgoing arc in the time expansion. More... | |
Arc | nextin (Arc arc) const |
Returns the id of the next incoming arc in the time expansion. More... | |
OutList | outarcs (BaseNode bnode) const |
Return a list of outgoing arcs of a node. | |
InList | inarcs (BaseNode bnode) const |
Return a list of incoming arcs of a node. | |
Shortest path functions | |
void | force_active (Group grp, Time time_active) |
Forces the active subgraph to contain certain arcs. More... | |
Time | active_time (Group grp) const |
Return the active subgraph boundary for the given group. | |
Result | shortest_path (const double basecosts[], const double augcosts[], index_type &nnodes, index_type &narcs) |
Solve the shortest path problem. More... | |
Result | shortest_path (const std::vector< double > &basecosts, const std::vector< double > &augcosts, index_type &nnodes, index_type &narcs) |
Result | shortest_path (const double basecosts[], const double augcosts[]) |
Result | shortest_path (const std::vector< double > &basecosts, const std::vector< double > &augcosts) |
index_type | get_n_newnodes () const |
Return number of new nodes of last expansion. | |
index_type | get_n_newarcs () const |
Return number of new arcs of last expansion. | |
index_type | get_pathlen () const |
Return the length of the shortest path. More... | |
double | get_path (Arc path[]) const |
Returns the latest computed shortest path. More... | |
double | get_path (std::vector< Arc > &path) const |
This is an overloaded member function, provided for convenience. It differs from the above function only in what argument(s) it accepts. More... | |
index_type | get_num_new_active () const |
Return the number of newly activated arcs. More... | |
void | get_new_active (Arc active[]) const |
Return the list of newly activated arcs. More... | |
void | get_new_active (std::vector< Arc > &active) const |
Return the list of newly activated arcs. More... | |
Static Public Attributes | |
static const Node | nonode = -1 |
ID of a non-existing node. | |
static const Arc | noarc = -2 |
ID of a non-existing arc. | |
A dynamic time expanded network.
This is the central class representing a time expanded network. In the following we give a formal definition of time expanded networks as they are understood by this class as well as the problems to be solved with the help of this class. For an in-depth discussion on the topic of dynamic graph generation we refer to [1].
Contents:
In this section we give a short overview over the theoretical ideas behind the dynamic graph generation approach implemented in this class.
A time expanded network is defined as follows.
Let be a finite, acyclic (except for loops), connected, directed graph with a unique source node and a sink node . Furthermore, assume that the nodes can be partitioned into so called groups (or equivalence classes) . The groups must satisfy the following three properties:
The graph is called the base graph of the time expanded network. In order to define the time expansion of let be the set of (discrete) time steps. Each arc of the base graph is assigned a non-empty, finite set of non-negative transfer times
such that for each loop .
The follow picture shows an example of a base graph with exactly one running time assigned to each arc.
The following picture shows the time expansion of the above base graph.
The problem to be solved in is a to find a minimum-cost path from a node to a node . For this, the user has to provide a weight function that assigns each arc of a weight:
Note that is acyclic, so negative weights are allowed. The problem to be solved is then
where
and
denotes the sum of the weights of the edges in the path .
There are several difficulties in solving this problem mainly related to the fact that the time expansion $ is extremely large, even infinite in the definition above. This has several theoretical and practical consequences:
In order to overcome these problems, the dynamic graph generation approach has been developed in [1]. The idea is to store only a small finite subgraph and to solve the shortest path problem only on . The algorithm then automatically detects whether the resulting path is a solution of the shortest path problem on the whole graph or otherwise enlarges by adding further nodes and arcs. Then the shortest path problem is resolved on the enlarged graph. It can be shown that, under some conditions, this approach finds a shortest path in after a finite number of iterations.
In order to be able to apply the dynamic graph generation approach, several conditions on the weight function must be satisfied.
The most important condition to ensure is the last one, which is a structural assumption on the basic objective function. The non-negativity condition on , however, is often met easily depending on the problem context. For instance, dynamic graph generation is designed to be used in Lagrangian relaxation approaches, where corresponds to the augmented costs induced by the Lagrangian multipliers of some coupling constraints. If these coupling constraints are inequalities with non-negative coefficients (which is typically the case for resource constraints), these augmented costs are automatically non-negative.
Remark: although the split of into and is often defined by the problem context, any valid decomposition works. In fact, one only has to ensure that is a lower bound (but increasing) on the real objective functions so that the residual term is non-negative. In fact, can be thought of a well behaving, convex lower bound on . However, a tighter (larger) typically leads to less iterations of the dynamic graph generation cycle until the shortest path in is found (and keeps the stored subgraph smaller). Hence, it is favorable to choose as large as possible.
In this section we describe how to use the Net class for implementing a dynamic graph generation approach. The Net class consists of the following three components:
The first step in using Net is to specify the base graph . The base graph consists of a finite set of nodes and arcs . Nodes and arcs are always numbered starting at 0, a new node or arc is assigned the smallest unused integer number. Furthermore, the set of base nodes is partitioned into a family of groups, also numbered from . Finally, each base arc is associated with a finite number of non-negative integer running times.
In order to specify the base graph one has to do the following steps: -# add the required number of groups using the methods Net::add_group and Net::add_groups,
A wait node is specified by adding a loop . Note that the only valid running time for loops is .
The base graph can be queried by iterating over the incoming and outgoing arcs of a node using the methods Net::base_firstin, Net::base_nextin, Net::base_inarcs and Net::base_firstout, Net::base_nextout, Net::base_outarcs.
The following code demonstrates how to create the base graph shown in Fig1.
The time expansion or, more accurately, the subgraph , is generated automatically. The graph is initialized by calling Net::init after creating the base graph. After calling Net::init the base graph must not be modified anymore.
The nodes and arcs of the time expansion may be queried in very much the same way as the base graph. Furthermore Net contains methods to query attributes of the nodes and arcs, e.g., the associated base node and time indices associated with a node. In particular, the attribute Net::isactive returns a flag indicating whether an arc is contained in the active subgraph or not.
The following code prints some information about all nodes and arcs in the time expansion.
The basic function to solve the shortest path problem is Net::shortest_path. This function is called with four arguments: the basic objective function basecosts
( ), the augmented costs augcosts
( ) and two output parameters nnodes
and narcs
. The two objective functions are arrays of weight values for each existing arc (i.e. the weights of an arc are basecosts[a]
and augcosts[a]
, respectively). The function returns either Result::Solved, if the shortest path problem in has been solved successfully, or Result::Expanded if the stored subgraph was too small and has been enlarged.
The interpretation of the variables nnodes
and narcs
depends on the return value of Net::shortest_path. If the return value is Result::Solved, they contain the number of nodes and arcs in the shortest path. The shortest path itself can be queried using Net::get_path.
If the return value is Result::Expanded, the shortest path problem could not be solved. In this case the graph has been enlarged by adding further nodes and arcs. The number of new nodes and arcs is returned in the two variables nnodes
and narcs
.
In order to solve the shortest path problem, the user must call Net::shortest_path in loop as long as the return value is Result::Expanded. In that case the arrays containing the objective function basecosts
and augcosts
must be enlarged by the user to contain the values for the new arcs. Then the shortest path problem must be resolved.
If the problem has been solved, the shortest path as well as its length can be retrieved using the Net::get_path method.
The following example demonstrates how to solve the shortest path problem.
|
strong |
Return states of the shortest path computation.
Enumerator | |
---|---|
Solved | The shortest path problem has been solved. |
Expanded | The shortest path problem has not been solved because the algorithm detected that the time expansion is too small. |
Dyng::Net::Net | ( | ) |
Constructor.
std::bad_alloc |
Add an arc to the base graph.
bsrc | the source base node |
bsnk | the sink base node |
bsrc
and bsnk
must be valid node numbers std::bad_alloc | |
std::invalid_argument | a precondition is violated |
Add a base node to the network.
group | the group number of the new node |
group
must be a valid group number std::bad_alloc | |
std::invalid_argument | a precondition is violated |
Group Dyng::Net::add_group | ( | ) |
Add one group to the base graph.
std::bad_alloc |
Group Dyng::Net::add_groups | ( | index_type | ngroups | ) |
Add several groups to the base graph.
The new groups are numbered in ascending order, the number of the first group is returned.
ngroups | the number of new groups to be added. |
ngroups > 0
std::bad_alloc |
Add one possible running time to a base arc.
arc | the base arc |
running_time | a possible running time |
arc
must be a valid arc number running_time >= 0
running_time == 1
if the arc is a loop std::bad_alloc | |
std::invalid_argument | a precondition is violated |
Add several possible running times to a base arc.
arc | the base arc |
ntimes | the number of new running times |
running_times | an array of new running times |
arc
must be a valid arc number ntimes >= 0
running_times[i] >= 0
for all i running_times[i] == 1
for all i if arc is a loop running_times
must contain at least ntimes
values, otherwise the behaviour is undefined std::bad_alloc | |
std::invalid_argument | a precondition is violated |
|
inline |
This is an overloaded member function, provided for convenience. It differs from the above function only in what argument(s) it accepts.
Returns the id of an arc in the time expansion.
The arc is identified by its source and sink nodes.
src | the id of the source node in the time expansion |
snk | the id of the sink node in the time expansion |
src
and snk
must be valid node ids. <tt>noarc</tt> | if the arc does not exist |
std::invalid_argument | a precondition is violated |
Returns the id of a base arc.
The arc is identified by its source and sink nodes.
bsrc | the id of the source node |
bsnk | the id of the sink node |
bsrc
and bsnk
must be valid node ids. <tt>noarc</tt> | if the arc does not exist |
std::invalid_argument | a precondition is violated |
Return first incoming arc of a node in the base graph.
bnode | the base node |
bnode
must be a valid node number noarc
if no such arc exists std::invalid_argument | a precondition is violated |
Return first outgoing arc of a node in the base graph.
bnode | the base node |
bnode
must be a valid node number noarc
if no such arc exists std::invalid_argument | a precondition is violated |
Returns the index of the group of a base node.
bnode | the ID of the base node |
bnode
must be a valid std::invalid_argument | if bnode is invalid |
index_type Dyng::Net::base_groupidx | ( | BaseNode | bnode | ) | const |
Returns the number of the node in its group.
The bases nodes contained in the same group are numbered in the order they have been added to the network. This function returns this index.
bnode | the ID of the base node |
bnode
must be valid std::invalid_argument | if bnode is invalid |
Return the next incoming base arc.
The next incoming arc is an arc with the same sink node.
arc | the base arc |
arc
must be a valid arc number noarc
if no such arc exists std::invalid_argument | a precondition is violated |
Return the next outgoing base arc.
The next outgoing arc is an arc with the same source node.
arc | the base arc |
arc
must be a valid arc number noarc
if no such arc exists std::invalid_argument | a precondition is violated |
Return the number of the sink base node of a base arc.
arc | the base arc |
arc
must be a valid arc number std::invalid_argument | a precondition is violated |
Return the number of the source base node of a base arc.
arc | the base arc |
arc
must be a valid arc number std::invalid_argument | a precondition is violated |
bool Dyng::Net::base_waitnode | ( | BaseNode | bnode | ) | const |
Returns true if the base node is a wait node.
bnode | the ID of the base node |
bnode
must be valid std::invalid_argument | if bnode is invalid |
Return the minimal possible time associated with a basenode.
bnode | the id of the base node |
bnode
must be a valid base node id std::invalid_argument | a precondition is violated |
Returns the id of an arc in the time expansion.
The arc is specified by id and time index of its source and sink Nodes.
bsrc | the id of the source base node |
srctime | the time of the source node |
bsnk | the id of the sink base node |
snktime | the time of the sink node |
nonode | if source or sink node are not (yet) contained in the network |
noarc | if the arc is not contained in the time expansion. Note that if DYNG_NOARC is returned then both nodes do exist, so the requested arc will never be contained in the time expansion. |
std::invalid_argument | a precondition is violated |
Returns the id of the first incoming arc in the time expansion.
node | the id of the node |
node
must be a valid node id <tt>noarc</tt> | if no incoming arc exists |
std::invalid_argument | a precondition is violated |
Returns the id of the first outgoing arc in the time expansion.
node | the id of the node |
node
must be a valid node id <tt>noarc</tt> | if no outgoing arc exists |
std::invalid_argument | a precondition is violated |
Forces the active subgraph to contain certain arcs.
All arcs leaving a base node of the given group up to a certain time index are forced to be contained in the active subgraph.
The graph will not be expanded immediately but at the next shortest path computation. Note that this might enlarge the graph at the next iteration.
grp | the group from which the new active arcs will leave |
time | first time index not contained in the active subgraph |
void Dyng::Net::get_new_active | ( | Arc | active[] | ) | const |
Return the list of newly activated arcs.
These are the arcs that have become active in the last expansion. The number of new active arcs can be queried using get_num_new_active
.
void Dyng::Net::get_new_active | ( | std::vector< Arc > & | active | ) | const |
Return the list of newly activated arcs.
These are the arcs that have become active in the last expansion.
index_type Dyng::Net::get_num_new_active | ( | ) | const |
Return the number of newly activated arcs.
These are the arcs that have become active in the last expansion.
double Dyng::Net::get_path | ( | Arc | path[] | ) | const |
Returns the latest computed shortest path.
[out] | path | an array containing the arcs of the path in order |
DyngError | if no path is available (called shortest_path ?) |
double Dyng::Net::get_path | ( | std::vector< Arc > & | path | ) | const |
This is an overloaded member function, provided for convenience. It differs from the above function only in what argument(s) it accepts.
std::bad_alloc |
index_type Dyng::Net::get_pathlen | ( | ) | const |
Return the length of the shortest path.
DyngError | if no path is available (called shortest path ?) |
Return the minimal possible time associated with a group.
grp | the id of the group |
grp
must be a valid group id std::invalid_argument | a precondition is violated |
void Dyng::Net::init | ( | ) |
Initializes the time expansion.
This function initializes the necessary data structures for the time expansion. After calling this function, the base graph must not modified anymore, and each attempt to do so will raise an error.
DyngError | if the base graph does not satisfy all conditions |
bool Dyng::Net::isactive | ( | Arc | arc | ) | const |
Returns true iff the given arc is contained in the active subgraph.
arc | the id of the arc |
arc
must be a valid arc id std::invalid_argument | a precondition is violated |
index_type Dyng::Net::n_arcs | ( | ) | const |
Returns the number of arcs in the time expansion.
index_type Dyng::Net::n_basearcs | ( | ) | const |
Return the number of base arcs.
index_type Dyng::Net::n_basenodes | ( | ) | const |
Return the number of base nodes.
index_type Dyng::Net::n_groups | ( | ) | const |
Return the number of groups in the base graph.
index_type Dyng::Net::n_nodes | ( | ) | const |
Returns the number of nodes in the time expansion.
Returns the id of the next incoming arc in the time expansion.
The next incoming arc is an arc with the same sink node.
arc | the id of the arc |
arc
must be a valid arc id <tt>noarc</tt> | if no next incoming arc exists |
std::invalid_argument | a precondition is violated |
Returns the id of the next outgoing arc in the time expansion.
The next outgoing arc is an arc with the same source node.
arc | the id of the arc |
arc
must be a valid arc id <tt>noarc</tt> | if no next outgoing arc exists |
std::invalid_argument | a precondition is violated |
Returns the id of a node in the time expansion.
The node is identified by its base node id and time index.
bnode | the id of the base node |
time | the time index of the node |
nonode | if the node does not (yet) exist |
std::invalid_argument | a precondition is violated |
Result Dyng::Net::shortest_path | ( | const double | basecosts[], |
const double | augcosts[], | ||
index_type & | nnodes, | ||
index_type & | narcs | ||
) |
Solve the shortest path problem.
The shortest path problem is solved w.r.t. the cost values given in basecosts
and augcosts
. If an arc is contained in the active subgraph then its weight is basecosts[arc] + augcosts[arc]
, otherwise it is basecosts[arc]
. The solution may fail if the resulting path is not contained in the active subgraph. In this case the time expansion is enlarged and nnodes
and narcs
are set to the number of new node and arcs, respectively, and Result::Expanded is returned. The shortest path problem must be solved again with enlarged cost vectors. If the resulting path is contained in the active subgraph then the solution succeeds. Then narcs
is set to the number of arcs in the shortest path and Result::Solved is returned.
The computed shortest path can be obtained by Net::get_path.
[in] | basecosts | the basic objective function |
[in] | augcosts | the augmented cost terms |
[out] | nnodes | the number of newly generated nodes |
[out] | narcs | the number of newly generated arcs or the length of the shortest path |
Result::Solved | if the shortest path problem could be solved |
Result::Expanded | if the time expansion must be expanded |
DyngError | if the time expansion has not been initialized |
Result Dyng::Net::shortest_path | ( | const std::vector< double > & | basecosts, |
const std::vector< double > & | augcosts, | ||
index_type & | nnodes, | ||
index_type & | narcs | ||
) |
This is an overloaded member function, provided for convenience. It differs from the above function only in what argument(s) it accepts.
Result Dyng::Net::shortest_path | ( | const double | basecosts[], |
const double | augcosts[] | ||
) |
This is an overloaded member function, provided for convenience. It differs from the above function only in what argument(s) it accepts.
Result Dyng::Net::shortest_path | ( | const std::vector< double > & | basecosts, |
const std::vector< double > & | augcosts | ||
) |
This is an overloaded member function, provided for convenience. It differs from the above function only in what argument(s) it accepts.
Returns the id of the sink node of an arc in the time expansion.
arc | the id of the arc |
arc
must be a valid arc id std::invalid_argument | a precondition is violated |
Returns the id of the source node of an arc in the time expansion.
arc | the id of the arc |
arc
must be a valid arc id std::invalid_argument | a precondition is violated |