Skip to content
GitLab
Explore
Sign in
Register
Primary navigation
Search or go to…
Project
gmsh
Manage
Activity
Members
Labels
Plan
Issues
Issue boards
Milestones
Wiki
Code
Merge requests
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Snippets
Build
Pipelines
Jobs
Pipeline schedules
Artifacts
Deploy
Releases
Model registry
Operate
Environments
Monitor
Incidents
Analyze
Value stream analytics
Contributor analytics
CI/CD analytics
Repository analytics
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
Community forum
Contribute to GitLab
Provide feedback
Terms and privacy
Keyboard shortcuts
?
Snippets
Groups
Projects
Show more breadcrumbs
Larry Price
gmsh
Commits
6c4266f1
Commit
6c4266f1
authored
8 years ago
by
Kilian Verhetsel
Browse files
Options
Downloads
Patches
Plain Diff
Added a file containing generic search algorithms
parent
4f43cead
Branches
Branches containing commit
Tags
Tags containing commit
No related merge requests found
Changes
1
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
Mesh/search.hpp
+329
-0
329 additions, 0 deletions
Mesh/search.hpp
with
329 additions
and
0 deletions
Mesh/search.hpp
0 → 100644
+
329
−
0
View file @
6c4266f1
#include
<vector>
#include
<queue>
#include
<iterator>
#include
<functional>
#include
<algorithm>
#include
<chrono>
#include
<boost/functional.hpp>
namespace
search
{
template
<
typename
T
>
struct
successor_traits
{
typedef
typename
T
::
action_type
action_type
;
};
template
<
typename
T
>
struct
action_traits
{
typedef
typename
boost
::
unary_traits
<
T
>::
result_type
delta_type
;
};
template
<
typename
T
>
struct
evaluator_traits
{
typedef
typename
boost
::
unary_traits
<
T
>::
result_type
score_type
;
};
template
<
typename
T
>
struct
selector_traits
{
typedef
typename
boost
::
unary_traits
<
T
>::
result_type
fragment_type
;
};
template
<
typename
T
>
struct
search_traits
{
typedef
typename
boost
::
binary_traits
<
T
>::
result_type
assignment_type
;
};
template
<
typename
State
,
typename
Visitor
,
typename
Successor
,
typename
Action
=
typename
successor_traits
<
Successor
>
::
action_type
,
typename
Delta
=
typename
action_traits
<
Action
>::
delta_type
>
void
depth_first_search
(
State
&
init
,
Visitor
&
visit
,
Successor
&
fn
)
{
visit
(
init
);
std
::
vector
<
Action
>
actions
;
fn
(
init
,
std
::
back_inserter
(
actions
));
for
(
const
Action
&
action
:
actions
)
{
Delta
change
(
action
(
init
));
change
.
apply
(
init
);
depth_first_search
(
init
,
visit
,
fn
);
change
.
reverse
(
init
);
}
}
template
<
typename
State
,
typename
Visitor
,
typename
Successor
,
typename
Action
=
typename
successor_traits
<
Successor
>
::
action_type
,
typename
Delta
=
typename
action_traits
<
Action
>::
delta_type
>
void
depth_limited_search
(
State
&
init
,
Visitor
&
visit
,
Successor
&
fn
,
size_t
max_depth
)
{
visit
(
init
);
if
(
max_depth
==
0
)
return
;
std
::
vector
<
Action
>
actions
;
fn
(
init
,
std
::
back_inserter
(
actions
));
for
(
const
Action
&
action
:
actions
)
{
Delta
change
(
action
(
init
));
change
.
apply
(
init
);
depth_limited_search
(
init
,
visit
,
fn
,
max_depth
-
1
);
change
.
reverse
(
init
);
}
}
template
<
typename
State
,
typename
Visitor
,
typename
Successor
,
typename
Queue
,
typename
Action
=
typename
successor_traits
<
Successor
>
::
action_type
,
typename
Delta
=
typename
action_traits
<
Action
>::
delta_type
>
void
tree_search
(
State
&
init
,
Visitor
&
visit
,
Successor
&
fn
,
Queue
q
)
{
q
.
push
(
init
);
while
(
!
q
.
empty
())
{
State
s
=
q
.
top
();
q
.
pop
();
visit
(
s
);
std
::
vector
<
Action
>
actions
;
fn
(
s
,
std
::
back_inserter
(
actions
));
for
(
const
Action
&
action
:
actions
)
{
State
to_add
(
s
);
action
(
s
).
apply
(
to_add
);
q
.
push
(
to_add
);
}
}
}
template
<
typename
State
,
typename
Visitor
,
typename
Successor
,
typename
Action
=
typename
successor_traits
<
Successor
>
::
action_type
,
typename
Delta
=
typename
action_traits
<
Action
>::
delta_type
>
void
breadth_first_search
(
State
&
init
,
Visitor
&
visit
,
Successor
&
fn
)
{
tree_search
(
init
,
visit
,
fn
,
std
::
queue
<
State
>
());
}
template
<
typename
State
,
typename
Visitor
,
typename
Successor
,
typename
Compare
=
std
::
less
<
State
>,
typename
Action
=
typename
successor_traits
<
Successor
>::
action_type
,
typename
Delta
=
typename
action_traits
<
Action
>::
delta_type
>
void
best_first_search
(
State
&
init
,
Visitor
&
visit
,
Successor
&
fn
,
Compare
c
=
Compare
())
{
tree_search
(
init
,
visit
,
fn
,
std
::
priority_queue
<
State
,
Compare
>
(
c
));
}
/**
* At each step, the successor returned through fn which maximizes eval, until
* reaching a node which has no successors.
*/
template
<
typename
State
,
typename
Successor
,
typename
Evaluator
,
typename
Action
=
typename
successor_traits
<
Successor
>
::
action_type
,
typename
Delta
=
typename
action_traits
<
Action
>::
delta_type
,
typename
Score
=
typename
evaluator_traits
<
Evaluator
>::
score_type
>
void
greedy_search
(
State
&
state
,
Successor
&
fn
,
Evaluator
&
eval
)
{
while
(
true
)
{
std
::
vector
<
Action
>
actions
;
fn
(
state
,
std
::
back_inserter
(
actions
));
if
(
actions
.
empty
())
return
;
if
(
actions
.
size
()
==
1
)
{
actions
[
0
](
state
).
apply
(
state
);
continue
;
}
std
::
vector
<
Delta
>
changes
(
actions
.
size
());
std
::
transform
(
actions
.
begin
(),
actions
.
end
(),
changes
.
begin
(),
[
&
](
const
Action
&
a
)
{
return
a
(
state
);
});
std
::
vector
<
Score
>
scores
(
actions
.
size
());
std
::
transform
(
changes
.
begin
(),
changes
.
end
(),
scores
.
begin
(),
[
&
](
const
Delta
&
delta
)
{
delta
.
apply
(
state
);
auto
result
=
eval
(
state
);
delta
.
reverse
(
state
);
return
result
;
});
auto
it
=
std
::
max_element
(
scores
.
begin
(),
scores
.
end
());
size_t
index
=
std
::
distance
(
scores
.
begin
(),
it
);
changes
[
index
].
apply
(
state
);
}
}
template
<
typename
State
,
typename
Selector
,
typename
Search
,
typename
Fragment
=
typename
selector_traits
<
Selector
>
::
fragment_type
,
typename
Assigment
=
typename
search_traits
<
Search
>::
assignment_type
>
void
large_neighborhood_search
(
State
&
state
,
Selector
&
selector
,
Search
&
search
,
size_t
fragment_count
=
100
)
{
for
(
size_t
i
=
0
;
i
<
fragment_count
;
i
++
)
{
Fragment
fragment
(
selector
(
state
));
Assigment
assignment
(
search
(
state
,
fragment
));
assignment
(
state
,
fragment
);
}
}
template
<
typename
Score
>
struct
mcts_node
{
mcts_node
()
:
x_1
(
0
),
x_2
(
0
),
visit_count
(
0
),
children
(
0
)
{}
Score
x_1
,
x_2
;
size_t
visit_count
;
std
::
vector
<
mcts_node
>
children
;
void
update
(
Score
score
)
{
x_1
+=
score
;
x_2
+=
score
*
score
;
visit_count
++
;
}
Score
ucb1
(
std
::
size_t
n
)
const
{
if
(
visit_count
==
0
)
return
std
::
numeric_limits
<
Score
>::
max
();
else
return
(
x_1
/
visit_count
)
+
std
::
sqrt
(
2
*
std
::
log
(
Score
(
n
))
/
visit_count
);
}
std
::
size_t
best_child
(
std
::
size_t
n
)
const
{
auto
it
=
std
::
max_element
(
children
.
begin
(),
children
.
end
(),
[
&
](
const
mcts_node
<
Score
>
&
a
,
const
mcts_node
<
Score
>
&
b
)
{
return
a
.
ucb1
(
n
)
<
b
.
ucb1
(
n
);
});
return
std
::
distance
(
children
.
begin
(),
it
);
}
};
/**
* Runs a single Monte Carlo Simulation as part of a Monte Carlo Tree Search.
*
* This operation is done as follows:
* 1. Explore the seach tree of statistics (described by node), playing
* optimially according to those statistics, until reaching
* one of its leaves.
* 2. Perform a completely random simulation, starting from the leaf found at
* the previous step.
* 3. Update the statistics tree.
*/
template
<
typename
State
,
typename
Successor
,
typename
Evaluator
,
typename
Iterator
,
typename
Action
=
typename
successor_traits
<
Successor
>
::
action_type
,
typename
Delta
=
typename
action_traits
<
Action
>::
delta_type
,
typename
Score
=
typename
evaluator_traits
<
Evaluator
>::
score_type
>
void
mcts_simulation
(
mcts_node
<
Score
>
*
node
,
State
&
state
,
Successor
&
fn
,
Evaluator
&
eval
,
size_t
n
,
Iterator
action_begin
,
Iterator
action_end
)
{
std
::
vector
<
Action
>
actions
(
action_begin
,
action_end
);
std
::
vector
<
mcts_node
<
Score
>*>
ancestors
;
std
::
vector
<
Delta
>
changes
;
ancestors
.
push_back
(
node
);
bool
explore
=
true
;
while
(
!
actions
.
empty
())
{
std
::
size_t
i
;
if
(
explore
&&
node
->
children
.
size
()
==
0
)
{
node
->
children
.
resize
(
actions
.
size
());
i
=
rand
()
%
actions
.
size
();
node
=
&
node
->
children
[
i
];
ancestors
.
push_back
(
node
);
explore
=
false
;
}
else
if
(
explore
)
{
i
=
node
->
best_child
(
n
);
node
=
&
node
->
children
[
i
];
ancestors
.
push_back
(
node
);
}
else
{
i
=
rand
()
%
actions
.
size
();
}
Delta
change
=
actions
[
i
](
state
);
changes
.
push_back
(
change
);
change
.
apply
(
state
);
actions
.
clear
();
fn
(
state
,
std
::
back_inserter
(
actions
));
}
Score
score
(
eval
(
state
));
for
(
mcts_node
<
Score
>
*
node
:
ancestors
)
node
->
update
(
score
);
for
(
auto
it
=
changes
.
rbegin
();
it
!=
changes
.
rend
();
it
++
)
(
*
it
).
reverse
(
state
);
}
template
<
typename
State
,
typename
Successor
,
typename
Evaluator
,
typename
Action
=
typename
successor_traits
<
Successor
>
::
action_type
,
typename
Delta
=
typename
action_traits
<
Action
>::
delta_type
,
typename
Score
=
typename
evaluator_traits
<
Evaluator
>::
score_type
>
void
monte_carlo_tree_search
(
State
&
state
,
Successor
&
fn
,
Evaluator
&
eval
)
{
std
::
vector
<
Action
>
actions
;
while
(
true
)
{
actions
.
clear
();
fn
(
state
,
std
::
back_inserter
(
actions
));
std
::
cout
<<
"
\r
score: "
<<
eval
(
state
);
std
::
cout
.
flush
();
if
(
actions
.
empty
())
break
;
else
if
(
actions
.
size
()
==
1
)
{
actions
[
0
](
state
).
apply
(
state
);
}
else
{
using
namespace
std
::
chrono
;
mcts_node
<
Score
>
node
;
size_t
i
;
auto
start
=
steady_clock
::
now
();
for
(
i
=
0
;
(
steady_clock
::
now
()
-
start
)
<
1s
;
i
++
)
{
mcts_simulation
(
&
node
,
state
,
fn
,
eval
,
i
,
actions
.
begin
(),
actions
.
end
());
}
actions
[
node
.
best_child
(
i
)](
state
).
apply
(
state
);
}
}
}
}
This diff is collapsed.
Click to expand it.
Preview
0%
Loading
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