Skip to content
GitLab
Explore
Sign in
Primary navigation
Search or go to…
Project
P
psco-2019-gp
Manage
Activity
Members
Labels
Plan
Issues
0
Issue boards
Milestones
Wiki
Requirements
Code
Merge requests
0
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Snippets
Locked files
Build
Pipelines
Jobs
Pipeline schedules
Test cases
Artifacts
Deploy
Releases
Container Registry
Model registry
Operate
Environments
Monitor
Incidents
Analyze
Value stream analytics
Contributor analytics
CI/CD analytics
Repository analytics
Code review analytics
Issue analytics
Insights
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
Community forum
Contribute to GitLab
Provide feedback
Keyboard shortcuts
?
Snippets
Groups
Projects
Show more breadcrumbs
Julian Scherzer
psco-2019-gp
Commits
e0048326
Commit
e0048326
authored
5 years ago
by
Florian Heinrichs
Browse files
Options
Downloads
Patches
Plain Diff
forced assignments
parent
aa444594
Branches
Branches containing commit
2 merge requests
!11
Forced assignments
,
!10
Forced assignments
Changes
4
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
bnb/bnb.cpp
+40
-19
40 additions, 19 deletions
bnb/bnb.cpp
bnb/greedy_packing.cpp
+121
-21
121 additions, 21 deletions
bnb/greedy_packing.cpp
include/gp-bnb/bnb.hpp
+2
-0
2 additions, 0 deletions
include/gp-bnb/bnb.hpp
include/gp-bnb/greedy_packing.hpp
+31
-6
31 additions, 6 deletions
include/gp-bnb/greedy_packing.hpp
with
194 additions
and
46 deletions
bnb/bnb.cpp
+
40
−
19
View file @
e0048326
...
...
@@ -26,45 +26,38 @@ void trail_state::pop() {
// solver implementation.
// --------------------------------------------------------------------------------------
solver
::
solver
(
graph
&
g
,
lb
lb_algorithm
)
:
graph_
(
g
),
partition_
(
partition
{
g
}),
lb_algorithm_
(
lb_algorithm
),
i_bfs_
(
incremental_bfs
(
g
))
{
solver
::
solver
(
graph
&
g
,
lb
lb_algorithm
)
:
graph_
(
g
),
partition_
(
partition
{
g
}),
lb_algorithm_
(
lb_algorithm
),
i_bfs_
(
incremental_bfs
(
g
))
,
gp_
(
greedy_packing
(
g
,
i_bfs_
,
true
))
{
}
unsigned
int
solver
::
get_lower
(){
std
::
vector
<
node_id
>
sources
,
sinks
;
for
(
node_id
node
=
1
;
node
<=
graph_
.
num_nodes
();
node
++
){
if
(
partition_
.
assigned_subgraph_of
(
node
)
==
partition
::
sg_a
)
sources
.
push_back
(
node
);
else
if
(
partition_
.
assigned_subgraph_of
(
node
)
==
partition
::
sg_b
)
sinks
.
push_back
(
node
);
}
if
(
sources
.
empty
()
||
sinks
.
empty
())
{
if
(
sources_
.
empty
()
||
sinks_
.
empty
())
{
return
partition_
.
current_objective
();
}
if
(
lb_algorithm_
==
lb
::
ek
){
auto
ek
=
edmonds_karp
(
graph_
,
sources
,
sinks
);
auto
ek
=
edmonds_karp
(
graph_
,
sources
_
,
sinks
_
);
ek
.
run
();
return
ek
.
get_max_flow
();
}
else
if
(
lb_algorithm_
==
lb
::
ibfs
){
i_bfs_
.
reset
(
sources
,
sinks
);
i_bfs_
.
reset
(
sources
_
,
sinks
_
);
i_bfs_
.
run
();
return
i_bfs_
.
get_max_flow
();
}
else
if
(
lb_algorithm_
==
lb
::
pr
){
auto
pr
=
push_relabel
(
graph_
,
sources
,
sinks
);
auto
pr
=
push_relabel
(
graph_
,
sources
_
,
sinks
_
);
pr
.
run
();
return
pr
.
get_max_flow
();
}
else
if
(
lb_algorithm_
==
lb
::
gp
){
bool
with_flow
=
true
;
auto
g_p
=
greedy_packing
(
graph_
,
sources
,
sinks
,
i_bfs_
,
with_flow
);
g
_
p
.
run
();
gp_
.
reset
(
sources
_
,
sinks
_
);
gp
_
.
run
();
if
(
with_flow
)
return
g
_
p
.
get_max_flow
();
return
g
_
p
.
get_max_flow
()
+
partition_
.
current_objective
();
return
gp
_
.
get_max_flow
();
return
gp
_
.
get_max_flow
()
+
partition_
.
current_objective
();
}
return
partition_
.
current_objective
();
}
...
...
@@ -149,19 +142,44 @@ void solver::expand(node_id node, subgraph sg) {
// Search for an alternative BEFORE assigning the node.
// Because the node is not assigned, this calculation is easy.
subgraph
alt
;
bool
fa
=
true
;
visited_nodes
++
;
if
(
partition_
.
num_nodes_of
(
subgraph
::
sg_a
)
==
0
&&
partition_
.
num_nodes_of
(
subgraph
::
sg_b
)){
if
(
partition_
.
num_nodes_of
(
subgraph
::
none
)
==
graph_
.
num_nodes
(
)){
alt
=
subgraph
::
none
;
}
else
{
alt
=
next_possible_subgraph
(
node
,
static_cast
<
subgraph
>
(
sg
+
1
));
}
if
(
lb_algorithm_
==
lb
::
gp
&&
fa
&&
!
(
sources_
.
empty
()
||
sinks_
.
empty
())){
auto
x
=
gp_
.
forced_assignment
(
node
);
if
(
x
.
second
){
if
(
x
.
first
>
best_objective_
){
sg
=
subgraph
::
sg_b
;
alt
=
subgraph
::
none
;
}
}
else
{
if
(
!
(
x
.
first
>
best_objective_
)){
sg
=
subgraph
::
sg_b
;
}
//else{
//alt = subgraph::none;
//}
}
}
if
(
verbose
)
{
std
::
cerr
<<
"Assign node "
<<
node
<<
" to subgraph "
<<
sg
<<
std
::
endl
;
std
::
cerr
<<
" Alternative "
<<
alt
<<
std
::
endl
;
}
//std::cerr << "expand: " << node << " to: " << sg << std::endl;
partition_
.
assign_node
(
node
,
sg
);
trail_
.
push_node
(
node
,
alt
);
if
(
sg
==
subgraph
::
sg_a
)
sources_
.
push_back
(
node
);
else
sinks_
.
push_back
(
node
);
}
void
solver
::
backtrack
()
{
...
...
@@ -173,6 +191,9 @@ void solver::backtrack() {
trail_
.
pop
();
partition_
.
unassign_node
(
node
);
if
(
sources_
.
back
()
==
node
)
sources_
.
erase
(
sources_
.
begin
()
+
sources_
.
size
()
-
1
);
else
if
(
sinks_
.
back
()
==
node
)
sinks_
.
erase
(
sinks_
.
begin
()
+
sinks_
.
size
()
-
1
);
//std::cerr << "backtrack" << std::endl;
}
// Finds the next partition in which the given node can be placed.
...
...
@@ -181,7 +202,7 @@ subgraph solver::next_possible_subgraph(node_id node, subgraph m) {
assert
(
partition_
.
assigned_subgraph_of
(
node
)
==
subgraph
::
none
);
subgraph
sg
=
m
;
while
(
sg
<=
1
){
if
((
partition_
.
num_nodes_of
(
sg
)
*
2
)
<
graph_
.
num_nodes
())
return
sg
;
...
...
This diff is collapsed.
Click to expand it.
bnb/greedy_packing.cpp
+
121
−
21
View file @
e0048326
...
...
@@ -4,26 +4,37 @@
bool
do_swap
=
true
;
greedy_packing
::
greedy_packing
(
graph
&
g
,
std
::
vector
<
node_id
>
A
,
std
::
vector
<
node_id
>
B
,
incremental_bfs
&
ibfs
,
bool
with_flow
)
:
graph_
(
g
),
a
(
A
),
b
(
B
),
i_bfs
(
ibfs
),
with_flow_
(
with_flow
){
if
(
do_swap
&&
A
.
size
()
>
B
.
size
()){
std
::
swap
(
a
,
b
);
}
visited
.
resize
(
graph_
.
num_nodes
()
+
1
,
false
);
greedy_packing
::
greedy_packing
(
graph
&
g
,
incremental_bfs
&
ibfs
,
bool
with_flow
)
:
graph_
(
g
),
i_bfs
(
ibfs
),
with_flow_
(
with_flow
){
max_a
=
(
graph_
.
num_nodes
())
/
2
;
};
void
greedy_packing
::
reset
(
std
::
vector
<
node_id
>
a
,
std
::
vector
<
node_id
>
b
){
a_
=
a
;
b_
=
b
;
x_
.
clear
();
flow_edges
.
clear
();
partitioning
.
clear
();
in_part
.
assign
(
graph_
.
num_nodes
()
+
1
,
-
1
);
a_count
=
0
;
visited
.
assign
(
graph_
.
num_nodes
()
+
1
,
false
);
if
(
do_swap
&&
a
.
size
()
>
b
.
size
()){
std
::
swap
(
a_
,
b_
);
}
}
//breadth-first-search to determine neighbors of B
void
greedy_packing
::
bfs
(){
for
(
node_id
node
:
b
){
for
(
node_id
node
:
b
_
){
q
.
push
(
node
);
visited
[
node
]
=
true
;
}
for
(
node_id
node
:
a
){
for
(
node_id
node
:
a
_
){
visited
[
node
]
=
true
;
}
...
...
@@ -37,7 +48,7 @@ void greedy_packing::bfs(){
if
(
visited
[
v
]
==
false
){
//falls nicht(mit_flow angegeben und knoten unter den flow_edges ist)dann push in zu x
if
(
!
(
with_flow_
&&
(
std
::
find
(
flow_edges
.
begin
(),
flow_edges
.
end
(),
graph_
.
get_edge_id
(
node
,
v
))
!=
flow_edges
.
end
()))){
x
.
push_back
(
v
);
x
_
.
push_back
(
v
);
visited
[
v
]
=
true
;
}
}
...
...
@@ -49,29 +60,42 @@ void greedy_packing::bfs(){
};
void
greedy_packing
::
run
(){
flow_
=
0
;
//std::cerr << "run gp " << std::endl;
flow_
=
bound
=
0
;
if
(
with_flow_
){
//get all flow edges and the flow
i_bfs
.
reset
(
a
,
b
);
i_bfs
.
reset
(
a
_
,
b
_
);
i_bfs
.
run
();
flow_
=
i_bfs
.
get_max_flow
();
flow_edges
=
i_bfs
.
get_flow_edges
();
}
a_count
=
a
.
size
();
a_count
=
a
_
.
size
();
if
(
a_count
>=
max_a
)
return
;
//x per bfs konstruieren
bfs
();
/*
for(auto n : a_){
std::cerr << " " << n;
}
std::cerr << std::endl;
for(auto n : b_){
std::cerr << " " << n;
}
std::cerr << std::endl;
*/
//P konstruieren
partitioning
.
resize
(
x
.
size
());
partitioning
.
resize
(
x
_
.
size
());
//dafür für jeden nachbarn von B einen eigenen Block
for
(
unsigned
int
i
=
0
;
i
<
x
.
size
();
i
++
){
partitioning
[
i
].
push_back
(
x
[
i
]);
for
(
unsigned
int
i
=
0
;
i
<
x_
.
size
();
i
++
){
partitioning
[
i
].
push_back
(
x_
[
i
]);
in_part
[
x_
[
i
]]
=
i
;
}
//dann jeweils kleinsten block um einen nachbarn erweitern
...
...
@@ -79,12 +103,13 @@ void greedy_packing::run(){
bool
found_new_element
=
true
;
while
(
found_new_element
)
{
found_new_element
=
false
;
for
(
std
::
vector
<
node_id
>
partition
:
partitioning
)
{
node_id
v
=
partition
.
back
();
for
(
unsigned
int
i
=
0
;
i
<
partitioning
.
size
();
i
++
)
{
node_id
v
=
partition
ing
[
i
]
.
back
();
for
(
node_id
node
:
graph_
.
get_adjacency
(
v
))
{
if
(
!
visited
[
node
])
{
if
(
!
(
with_flow_
&&
(
std
::
find
(
flow_edges
.
begin
(),
flow_edges
.
end
(),
graph_
.
get_edge_id
(
node
,
v
))
!=
flow_edges
.
end
()))){
partition
.
push_back
(
node
);
partitioning
[
i
].
push_back
(
node
);
in_part
[
node
]
=
i
;
visited
[
node
]
=
true
;
found_new_element
=
true
;
break
;
...
...
@@ -112,7 +137,7 @@ void greedy_packing::run(){
// packe greedy (erst hier wird flow erhöht)
for
(
std
::
vector
<
node_id
>
partition
:
partitioning
)
{
flow_
++
;
bound
++
;
a_count
+=
partition
.
size
();
if
(
a_count
>=
max_a
){
return
;
...
...
@@ -122,5 +147,80 @@ void greedy_packing::run(){
return
;
};
std
::
pair
<
unsigned
int
,
bool
>
greedy_packing
::
forced_assignment
(
node_id
node
){
unsigned
int
new_bound
,
x_v
,
p
,
index
;
bool
case1
;
x_v
=
p
=
0
;
a_count
=
a_
.
size
();
/*
std::cerr << visited.size() << std::endl;
for(int i = 0; i < visited.size(); i++){
std::cerr << i << " : " << visited[i] << " ";
}
std::cerr << " node: " << node << std::endl;
for(int i = 0; i < in_part.size(); i++){
std::cerr << i << " : " << in_part[i] << " ";
}
std::cerr << std::endl;
*/
//fall 1: node in nicht trivialem block
if
(
visited
[
node
]){
//für jeden nachbarn von v
for
(
node_id
u
:
graph_
.
get_adjacency
(
node
)){
if
(
in_part
[
u
]
!=
-
1
){
//falls er in einem block liegt erhöhe x_v
x_v
++
;
index
=
in_part
[
u
];
//dieser block ist nun nicht trivial (jeden knoten nichtmehr
//als visited markieren)
for
(
node_id
v
:
partitioning
[
in_part
[
u
]]){
//std::cerr << v << " ";
visited
[
v
]
=
false
;
in_part
[
v
]
=
-
1
;
}
partitioning
[
index
].
clear
();
}
}
//neues eingeschränktes packing-bound berechnen
std
::
sort
(
partitioning
.
begin
(),
partitioning
.
end
(),
[](
std
::
vector
<
node_id
>
a
,
std
::
vector
<
node_id
>
b
)
{
return
a
.
size
()
>
b
.
size
();
});
// behandle von B aus unnerreichbare Knoten
for
(
node_id
i
=
1
;
i
<=
graph_
.
num_nodes
();
i
++
)
{
if
(
!
visited
[
i
])
{
a_count
++
;
if
(
a_count
>=
max_a
){
break
;
}
}
}
// packe greedy (erst hier wird flow erhöht)
for
(
std
::
vector
<
node_id
>
partition
:
partitioning
)
{
p
++
;
a_count
+=
partition
.
size
();
if
(
a_count
>=
max_a
){
break
;
}
}
new_bound
=
flow_
+
x_v
+
p
;
case1
=
true
;
}
else
{
//fall2: v in trivialem block
//bound erhöht sich um anzahl der nachbarn von v
new_bound
=
flow_
+
bound
+
graph_
.
get_adjacency
(
node
).
size
();
case1
=
false
;
}
return
std
::
make_pair
(
new_bound
,
case1
);
}
This diff is collapsed.
Click to expand it.
include/gp-bnb/bnb.hpp
+
2
−
0
View file @
e0048326
...
...
@@ -90,10 +90,12 @@ private:
lb
lb_algorithm_
;
incremental_bfs
i_bfs_
;
greedy_packing
gp_
;
// Value of best solution seen so far.
std
::
vector
<
subgraph
>
best_solution_
;
unsigned
int
best_objective_
=
0
;
std
::
vector
<
node_id
>
sources_
,
sinks_
;
};
}
// namespace gp_bnb
...
...
This diff is collapsed.
Click to expand it.
include/gp-bnb/greedy_packing.hpp
+
31
−
6
View file @
e0048326
...
...
@@ -5,17 +5,41 @@
#include
<vector>
#include
<gp-bnb/graph.hpp>
#include
<gp-bnb/incremental_bfs.hpp>
#include
<iostream>
class
greedy_packing
{
public:
greedy_packing
(
graph
&
g
,
std
::
vector
<
node_id
>
a
,
std
::
vector
<
node_id
>
b
,
incremental_bfs
&
ibfs
,
bool
with_flow
);
/** @brief Initializes a greedy-packing instance
* @param Graph to be partitioned
* @param iBFS instance to be used
* @param bool, if bound with flow should be used
*/
greedy_packing
(
graph
&
g
,
incremental_bfs
&
ibfs
,
bool
with_flow
);
/** @brief executes the GP algortihm
*/
void
run
();
/** @brief resets the already partitioned sets a and b
* @param vector of nodes in set a
* @param vector of nodes in set b
*/
void
reset
(
std
::
vector
<
node_id
>
a
,
std
::
vector
<
node_id
>
b
);
/** @brief executes the forced assignments algorithm
* @param node for which we decide the next branch
* @return pair of bool and int where bool represents if node
* was in trivial block or not
* int: new upper bound if we would branch
*/
std
::
pair
<
unsigned
int
,
bool
>
forced_assignment
(
node_id
node
);
/** @brief return the bound after execution
* @return packing-bound
*/
int
get_max_flow
()
const
{
return
flow_
;
return
flow_
+
bound
;
};
private
:
...
...
@@ -26,7 +50,8 @@ private:
//partial partition into blocks a and b
//x is block with the neighbors of B
std
::
vector
<
node_id
>
a
,
b
,
x
;
std
::
vector
<
node_id
>
a_
,
b_
,
x_
;
std
::
vector
<
int
>
in_part
;
incremental_bfs
&
i_bfs
;
...
...
@@ -40,7 +65,7 @@ private:
std
::
vector
<
bool
>
visited
;
unsigned
int
a_count
,
max_a
,
flow_
;
unsigned
int
a_count
,
max_a
,
flow_
,
bound
;
};
#endif
/* GREEDY_PACKING_H_ */
This diff is collapsed.
Click to expand it.
Preview
0%
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Save comment
Cancel
Please
register
or
sign in
to comment