Skip to content
Projects
Groups
Snippets
Help
Loading...
Sign in
Toggle navigation
D
dlib
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
钟尚武
dlib
Commits
f02e5477
Commit
f02e5477
authored
Nov 12, 2012
by
Davis King
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Added find_max_parse_cky() and its supporting tools.
parent
626cfb90
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
400 additions
and
0 deletions
+400
-0
optimization.h
dlib/optimization.h
+1
-0
find_max_parse_cky.h
dlib/optimization/find_max_parse_cky.h
+280
-0
find_max_parse_cky_abstract.h
dlib/optimization/find_max_parse_cky_abstract.h
+119
-0
No files found.
dlib/optimization.h
View file @
f02e5477
...
@@ -15,6 +15,7 @@
...
@@ -15,6 +15,7 @@
#include "optimization/max_sum_submatrix.h"
#include "optimization/max_sum_submatrix.h"
#include "optimization/find_max_factor_graph_nmplp.h"
#include "optimization/find_max_factor_graph_nmplp.h"
#include "optimization/find_max_factor_graph_viterbi.h"
#include "optimization/find_max_factor_graph_viterbi.h"
#include "optimization/find_max_parse_cky.h"
#endif // DLIB_OPTIMIZATIOn_HEADER
#endif // DLIB_OPTIMIZATIOn_HEADER
...
...
dlib/optimization/find_max_parse_cky.h
0 → 100644
View file @
f02e5477
// Copyright (C) 2012 Davis E. King (davis@dlib.net)
// License: Boost Software License See LICENSE.txt for the full license.
#ifndef DLIB_FIND_MAX_PaRSE_CKY_H__
#define DLIB_FIND_MAX_PaRSE_CKY_H__
#include "find_max_parse_cky_abstract.h"
#include <vector>
#include <string>
#include <sstream>
#include "../array2d.h"
namespace
dlib
{
// -----------------------------------------------------------------------------------------
template
<
typename
T
>
struct
constituent
{
unsigned
long
begin
,
end
,
k
;
T
left_tag
;
T
right_tag
;
};
const
unsigned
long
END_OF_TREE
=
0xFFFFFFFF
;
template
<
typename
T
>
struct
parse_tree_element
{
constituent
<
T
>
c
;
T
tag
;
// id for the constituent corresponding to this level of the tree
unsigned
long
left
;
unsigned
long
right
;
double
score
;
};
namespace
impl
{
template
<
typename
T
>
unsigned
long
fill_parse_tree
(
std
::
vector
<
parse_tree_element
<
T
>
>&
parse_tree
,
const
T
&
tag
,
const
array2d
<
std
::
map
<
T
,
parse_tree_element
<
T
>
>
>&
back
,
long
r
,
long
c
)
/*!
requires
- back[r][c].size() == 0 || back[r][c].count(tag) != 0
!*/
{
// base case of the recursion
if
(
back
[
r
][
c
].
size
()
==
0
)
{
return
END_OF_TREE
;
}
const
unsigned
long
idx
=
parse_tree
.
size
();
const
parse_tree_element
<
T
>&
item
=
back
[
r
][
c
].
find
(
tag
)
->
second
;
parse_tree
.
push_back
(
item
);
const
long
k
=
item
.
c
.
k
;
const
unsigned
long
idx_left
=
fill_parse_tree
(
parse_tree
,
item
.
c
.
left_tag
,
back
,
r
,
k
-
1
);
const
unsigned
long
idx_right
=
fill_parse_tree
(
parse_tree
,
item
.
c
.
right_tag
,
back
,
k
,
c
);
parse_tree
[
idx
].
left
=
idx_left
;
parse_tree
[
idx
].
right
=
idx_right
;
return
idx
;
}
}
template
<
typename
T
,
typename
production_rule_function
>
void
find_max_parse_cky
(
const
std
::
vector
<
T
>&
sequence
,
const
production_rule_function
&
production_rules
,
std
::
vector
<
std
::
vector
<
parse_tree_element
<
T
>
>
>&
parse_trees
)
{
parse_trees
.
clear
();
array2d
<
std
::
map
<
T
,
double
>
>
table
(
sequence
.
size
(),
sequence
.
size
());
array2d
<
std
::
map
<
T
,
parse_tree_element
<
T
>
>
>
back
(
sequence
.
size
(),
sequence
.
size
());
typedef
typename
std
::
map
<
T
,
double
>::
iterator
itr
;
typedef
typename
std
::
map
<
T
,
parse_tree_element
<
T
>
>::
iterator
itr_b
;
for
(
long
r
=
0
;
r
<
table
.
nr
();
++
r
)
table
[
r
][
r
][
sequence
[
r
]]
=
0
;
std
::
vector
<
std
::
pair
<
T
,
double
>
>
possible_tags
;
for
(
long
r
=
table
.
nr
()
-
2
;
r
>=
0
;
--
r
)
{
for
(
long
c
=
r
+
1
;
c
<
table
.
nc
();
++
c
)
{
for
(
long
k
=
r
;
k
<
c
;
++
k
)
{
for
(
itr
i
=
table
[
k
+
1
][
c
].
begin
();
i
!=
table
[
k
+
1
][
c
].
end
();
++
i
)
{
for
(
itr
j
=
table
[
r
][
k
].
begin
();
j
!=
table
[
r
][
k
].
end
();
++
j
)
{
constituent
<
T
>
con
;
con
.
begin
=
r
;
con
.
end
=
c
+
1
;
con
.
k
=
k
+
1
;
con
.
left_tag
=
j
->
first
;
con
.
right_tag
=
i
->
first
;
possible_tags
.
clear
();
production_rules
(
sequence
,
con
,
possible_tags
);
for
(
unsigned
long
m
=
0
;
m
<
possible_tags
.
size
();
++
m
)
{
const
double
score
=
possible_tags
[
m
].
second
+
i
->
second
+
j
->
second
;
itr
match
=
table
[
r
][
c
].
find
(
possible_tags
[
m
].
first
);
if
(
match
==
table
[
r
][
c
].
end
()
||
score
>
match
->
second
)
{
table
[
r
][
c
][
possible_tags
[
m
].
first
]
=
score
;
parse_tree_element
<
T
>
item
;
item
.
c
=
con
;
item
.
score
=
score
;
item
.
tag
=
possible_tags
[
m
].
first
;
back
[
r
][
c
][
possible_tags
[
m
].
first
]
=
item
;
}
}
}
}
}
}
}
// now use back pointers to build the parse trees
for
(
long
r
=
0
;
r
<
back
.
nr
();
++
r
)
{
for
(
long
c
=
back
.
nc
()
-
1
;
c
>
r
;
--
c
)
{
if
(
back
[
r
][
c
].
size
()
!=
0
)
{
// find the max scoring element in back[r][c]
itr_b
max_i
=
back
[
r
][
c
].
begin
();
itr_b
i
=
max_i
;
++
i
;
for
(;
i
!=
back
[
r
][
c
].
end
();
++
i
)
{
if
(
i
->
second
.
score
>
max_i
->
second
.
score
)
max_i
=
i
;
}
parse_trees
.
resize
(
parse_trees
.
size
()
+
1
);
parse_trees
.
back
().
reserve
(
c
);
impl
::
fill_parse_tree
(
parse_trees
.
back
(),
max_i
->
second
.
tag
,
back
,
r
,
c
);
r
=
c
;
break
;
}
}
}
}
// -----------------------------------------------------------------------------------------
class
parse_tree_to_string_error
:
public
error
{
public
:
parse_tree_to_string_error
(
const
std
::
string
&
str
)
:
error
(
str
)
{}
};
namespace
impl
{
template
<
bool
enabled
,
typename
T
>
typename
enable_if_c
<
enabled
>::
type
conditional_print
(
const
T
&
item
,
std
::
ostream
&
out
)
{
out
<<
item
<<
" "
;
}
template
<
bool
enabled
,
typename
T
>
typename
disable_if_c
<
enabled
>::
type
conditional_print
(
const
T
&
,
std
::
ostream
&
)
{
}
template
<
bool
print_tag
,
typename
T
,
typename
U
>
void
print_parse_tree_helper
(
const
std
::
vector
<
parse_tree_element
<
T
>
>&
tree
,
const
std
::
vector
<
U
>&
items
,
unsigned
long
i
,
std
::
ostream
&
out
)
{
out
<<
"["
;
bool
left_recurse
=
false
;
// Only print if we are supposed to. Doing it this funny way avoids compiler
// errors in parse_tree_to_string() for the case where tag isn't
// printable.
conditional_print
<
print_tag
>
(
tree
[
i
].
tag
,
out
);
if
(
tree
[
i
].
left
<
tree
.
size
())
{
left_recurse
=
true
;
print_parse_tree_helper
<
print_tag
>
(
tree
,
items
,
tree
[
i
].
left
,
out
);
}
else
{
if
(
tree
[
i
].
c
.
begin
<
items
.
size
())
{
out
<<
items
[
tree
[
i
].
c
.
begin
]
<<
" "
;
}
else
{
std
::
ostringstream
sout
;
sout
<<
"Parse tree refers to element "
<<
tree
[
i
].
c
.
begin
<<
" of sequence which is only of size "
<<
items
.
size
()
<<
"."
;
throw
parse_tree_to_string_error
(
sout
.
str
());
}
}
if
(
tree
[
i
].
right
<
tree
.
size
())
{
if
(
left_recurse
==
true
)
out
<<
" "
;
print_parse_tree_helper
<
print_tag
>
(
tree
,
items
,
tree
[
i
].
right
,
out
);
}
else
{
if
(
tree
[
i
].
c
.
k
<
items
.
size
())
{
out
<<
items
[
tree
[
i
].
c
.
k
];
}
else
{
std
::
ostringstream
sout
;
sout
<<
"Parse tree refers to element "
<<
tree
[
i
].
c
.
k
<<
" of sequence which is only of size "
<<
items
.
size
()
<<
"."
;
throw
parse_tree_to_string_error
(
sout
.
str
());
}
}
out
<<
"]"
;
}
}
// -----------------------------------------------------------------------------------------
template
<
typename
T
,
typename
U
>
std
::
string
parse_tree_to_string
(
const
std
::
vector
<
parse_tree_element
<
T
>
>&
tree
,
const
std
::
vector
<
U
>&
items
)
{
if
(
tree
.
size
()
==
0
)
return
""
;
std
::
ostringstream
sout
;
impl
::
print_parse_tree_helper
<
false
>
(
tree
,
items
,
0
,
sout
);
return
sout
.
str
();
}
// -----------------------------------------------------------------------------------------
template
<
typename
T
,
typename
U
>
std
::
string
parse_tree_to_string_tagged
(
const
std
::
vector
<
parse_tree_element
<
T
>
>&
tree
,
const
std
::
vector
<
U
>&
items
)
{
if
(
tree
.
size
()
==
0
)
return
""
;
std
::
ostringstream
sout
;
impl
::
print_parse_tree_helper
<
true
>
(
tree
,
items
,
0
,
sout
);
return
sout
.
str
();
}
// -----------------------------------------------------------------------------------------
}
#endif // DLIB_FIND_MAX_PaRSE_CKY_H__
dlib/optimization/find_max_parse_cky_abstract.h
0 → 100644
View file @
f02e5477
// Copyright (C) 2012 Davis E. King (davis@dlib.net)
// License: Boost Software License See LICENSE.txt for the full license.
#undef DLIB_FIND_MAX_PARsE_CKY_ABSTRACT_H__
#ifdef DLIB_FIND_MAX_PARsE_CKY_ABSTRACT_H__
#include <vector>
#include <string>
namespace
dlib
{
// -----------------------------------------------------------------------------------------
template
<
typename
T
>
struct
constituent
{
/*!
WHAT THIS OBJECT REPRESENTS
!*/
unsigned
long
begin
,
end
,
k
;
T
left_tag
;
T
right_tag
;
};
const
unsigned
long
END_OF_TREE
=
0xFFFFFFFF
;
template
<
typename
T
>
struct
parse_tree_element
{
/*!
WHAT THIS OBJECT REPRESENTS
!*/
constituent
<
T
>
c
;
T
tag
;
// id for the constituent corresponding to this level of the tree
// subtrees. These are the index values into the std::vector that contains all the parse_tree_elements.
unsigned
long
left
;
unsigned
long
right
;
double
score
;
// score for this tree
};
// -----------------------------------------------------------------------------------------
// -----------------------------------------------------------------------------------------
void
example_production_rule_function
(
const
std
::
vector
<
T
>&
sequence
,
const
constituent
<
T
>&
c
,
std
::
vector
<
std
::
pair
<
T
,
double
>
>&
possible_tags
)
/*!
requires
- 0 <= c.begin < c.k < c.end <= sequence.size()
- possible_tags.size() == 0
ensures
- finds all the production rules that can turn c into a single non-terminal.
Puts the IDs of these rules and their scores into possible_tags.
- Note that example_production_rule_function() is not a real function. It is
here just to show you how to define production rule producing functions
for use with the find_max_parse_cky() routine defined below.
!*/
template
<
typename
T
,
typename
production_rule_function
>
void
find_max_parse_cky
(
const
std
::
vector
<
T
>&
sequence
,
const
production_rule_function
&
production_rules
,
std
::
vector
<
std
::
vector
<
parse_tree_element
<
T
>
>
>&
parse_trees
);
/*!
requires
- production_rule_function == a function or function object with the same
interface as example_production_rule_function defined above.
!*/
// -----------------------------------------------------------------------------------------
// -----------------------------------------------------------------------------------------
class
parse_tree_to_string_error
:
public
error
{
/*!
WHAT THIS OBJECT REPRESENTS
!*/
};
// -----------------------------------------------------------------------------------------
template
<
typename
T
,
typename
U
>
std
::
string
parse_tree_to_string
(
const
std
::
vector
<
parse_tree_element
<
T
>
>&
tree
,
const
std
::
vector
<
U
>&
items
);
/*!
ensures
-
!*/
// -----------------------------------------------------------------------------------------
template
<
typename
T
,
typename
U
>
std
::
string
parse_tree_to_string_tagged
(
const
std
::
vector
<
parse_tree_element
<
T
>
>&
tree
,
const
std
::
vector
<
U
>&
items
);
/*!
ensures
-
!*/
// -----------------------------------------------------------------------------------------
}
#endif // DLIB_FIND_MAX_PARsE_CKY_ABSTRACT_H__
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment