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
5494e540
Commit
5494e540
authored
Sep 21, 2013
by
Davis King
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Added find_min_box_constrained()
parent
ef463112
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
322 additions
and
0 deletions
+322
-0
optimization.h
dlib/optimization/optimization.h
+133
-0
optimization_abstract.h
dlib/optimization/optimization_abstract.h
+54
-0
optimization.cpp
dlib/test/optimization.cpp
+135
-0
No files found.
dlib/optimization/optimization.h
View file @
5494e540
...
...
@@ -432,6 +432,139 @@ namespace dlib
);
}
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
// Functions for box constrained optimization
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
template
<
typename
T
,
typename
U
,
typename
V
>
T
zero_bounded_variables
(
const
double
eps
,
T
vect
,
const
T
&
x
,
const
T
&
gradient
,
const
U
&
x_lower
,
const
V
&
x_upper
)
{
for
(
long
i
=
0
;
i
<
gradient
.
size
();
++
i
)
{
const
double
tol
=
eps
*
std
::
abs
(
x
(
i
));
// if x(i) is an active bound constraint
if
(
x_lower
(
i
)
+
tol
>=
x
(
i
)
&&
gradient
(
i
)
>
0
)
vect
(
i
)
=
0
;
else
if
(
x_upper
(
i
)
-
tol
<=
x
(
i
)
&&
gradient
(
i
)
<
0
)
vect
(
i
)
=
0
;
}
return
vect
;
}
// ----------------------------------------------------------------------------------------
template
<
typename
T
,
typename
U
,
typename
V
>
T
gap_step_assign_bounded_variables
(
const
double
eps
,
T
vect
,
const
T
&
x
,
const
T
&
gradient
,
const
U
&
x_lower
,
const
V
&
x_upper
)
{
for
(
long
i
=
0
;
i
<
gradient
.
size
();
++
i
)
{
const
double
tol
=
eps
*
std
::
abs
(
x
(
i
));
// if x(i) is an active bound constraint then we should set it's search
// direction such that a single step along the direction either does nothing or
// closes the gap of size tol before hitting the bound exactly.
if
(
x_lower
(
i
)
+
tol
>=
x
(
i
)
&&
gradient
(
i
)
>
0
)
vect
(
i
)
=
x_lower
(
i
)
-
x
(
i
);
else
if
(
x_upper
(
i
)
-
tol
<=
x
(
i
)
&&
gradient
(
i
)
<
0
)
vect
(
i
)
=
x_upper
(
i
)
-
x
(
i
);
}
return
vect
;
}
// ----------------------------------------------------------------------------------------
template
<
typename
search_strategy_type
,
typename
stop_strategy_type
,
typename
funct
,
typename
funct_der
,
typename
T
,
typename
EXP1
,
typename
EXP2
>
double
find_min_box_constrained
(
search_strategy_type
search_strategy
,
stop_strategy_type
stop_strategy
,
const
funct
&
f
,
const
funct_der
&
der
,
T
&
x
,
const
matrix_exp
<
EXP1
>&
x_lower
,
const
matrix_exp
<
EXP2
>&
x_upper
)
{
// make sure the requires clause is not violated
COMPILE_TIME_ASSERT
(
is_matrix
<
T
>::
value
);
DLIB_ASSERT
(
is_col_vector
(
x
)
&&
is_col_vector
(
x_lower
)
&&
is_col_vector
(
x_upper
)
&&
x
.
size
()
==
x_lower
.
size
()
&&
x
.
size
()
==
x_upper
.
size
(),
"
\t
double find_min_box_constrained()"
<<
"
\n\t
The inputs to this function must be equal length column vectors."
<<
"
\n\t
is_col_vector(x): "
<<
is_col_vector
(
x
)
<<
"
\n\t
is_col_vector(x_upper): "
<<
is_col_vector
(
x_upper
)
<<
"
\n\t
is_col_vector(x_upper): "
<<
is_col_vector
(
x_upper
)
<<
"
\n\t
x.size(): "
<<
x
.
size
()
<<
"
\n\t
x_lower.size(): "
<<
x_lower
.
size
()
<<
"
\n\t
x_upper.size(): "
<<
x_upper
.
size
()
);
DLIB_ASSERT
(
min
(
x_upper
-
x_lower
)
>
0
,
"
\t
double find_min_box_constrained()"
<<
"
\n\t
You have to supply proper box constraints to this function."
<<
"
\n\r
min(x_upper-x_lower): "
<<
min
(
x_upper
-
x_lower
)
);
T
g
,
s
;
double
f_value
=
f
(
x
);
g
=
der
(
x
);
DLIB_ASSERT
(
is_finite
(
f_value
),
"The objective function generated non-finite outputs"
);
DLIB_ASSERT
(
is_finite
(
g
),
"The objective function generated non-finite outputs"
);
// gap_eps determines how close we have to get to a bound constraint before we
// start basically dropping it from the optimization and consider it to be an
// active constraint.
const
double
gap_eps
=
1e-8
;
while
(
stop_strategy
.
should_continue_search
(
x
,
f_value
,
g
))
{
s
=
search_strategy
.
get_next_direction
(
x
,
f_value
,
zero_bounded_variables
(
gap_eps
,
g
,
x
,
g
,
x_lower
,
x_upper
));
s
=
gap_step_assign_bounded_variables
(
gap_eps
,
s
,
x
,
g
,
x_lower
,
x_upper
);
double
alpha
=
backtracking_line_search
(
make_line_search_function
(
clamp_function
(
f
,
x_lower
,
x_upper
),
x
,
s
,
f_value
),
f_value
,
dot
(
g
,
s
),
// compute gradient for the line search
1
,
search_strategy
.
get_wolfe_rho
(),
search_strategy
.
get_max_line_search_iterations
());
// Take the search step indicated by the above line search
x
=
clamp
(
x
+
alpha
*
s
,
x_lower
,
x_upper
);
g
=
der
(
x
);
DLIB_ASSERT
(
is_finite
(
f_value
),
"The objective function generated non-finite outputs"
);
DLIB_ASSERT
(
is_finite
(
g
),
"The objective function generated non-finite outputs"
);
}
return
f_value
;
}
// ----------------------------------------------------------------------------------------
}
...
...
dlib/optimization/optimization_abstract.h
View file @
5494e540
...
...
@@ -277,6 +277,60 @@ namespace dlib
!*/
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
// Functions that perform box constrained optimization
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
template
<
typename
search_strategy_type
,
typename
stop_strategy_type
,
typename
funct
,
typename
funct_der
,
typename
T
,
typename
EXP1
,
typename
EXP2
>
double
find_min_box_constrained
(
search_strategy_type
search_strategy
,
stop_strategy_type
stop_strategy
,
const
funct
&
f
,
const
funct_der
&
der
,
T
&
x
,
const
matrix_exp
<
EXP1
>&
x_lower
,
const
matrix_exp
<
EXP2
>&
x_upper
);
/*!
requires
- search_strategy == an object that defines a search strategy such as one
of the objects from dlib/optimization/optimization_search_strategies_abstract.h
- stop_strategy == an object that defines a stop strategy such as one of
the objects from dlib/optimization/optimization_stop_strategies_abstract.h
- f(x) must be a valid expression that evaluates to a double
- der(x) must be a valid expression that evaluates to the derivative of f() at x.
- is_col_vector(x) == true
- is_col_vector(x_lower) == true
- is_col_vector(x_upper) == true
- x.size() == x_lower.size() == x_upper.size()
(i.e. x, x_lower, and x_upper need to all be column vectors of the same dimensionality)
- min(x_upper-x_lower) > 0
(i.e. x_upper must contain upper bounds relative to x_lower)
ensures
- Performs a box constrained minimization of the function f() using the given
search_strategy and starting from the initial point x. That is, we try to
find the x value that minimizes f(x) but is also within the box constraints
specified by x_lower and x_upper. That is, we ensure that #x satisfies:
- min(#x - x_lower) >= 0 && min(x_upper - #x) >= 0
- This function uses a backtracking line search along with a gradient projection
to handle the box constraints.
- The function is optimized until stop_strategy decides that an acceptable
point has been found.
- #x == the value of x that was found to minimize f() within the given box
constraints.
- returns f(#x).
- When calling f() and der(), the input passed to them will always be inside
the box constraints defined by x_lower and x_upper.
!*/
}
...
...
dlib/test/optimization.cpp
View file @
5494e540
...
...
@@ -2,7 +2,9 @@
// License: Boost Software License See LICENSE.txt for the full license.
#include "optimization_test_functions.h"
#include <dlib/optimization.h>
#include <dlib/statistics.h>
#include <sstream>
#include <string>
#include <cstdlib>
...
...
@@ -916,6 +918,135 @@ namespace
}
template
<
typename
der_funct
,
typename
T
>
double
unconstrained_gradient_magnitude
(
const
der_funct
&
grad
,
const
T
&
x
,
const
T
&
lower
,
const
T
&
upper
)
{
T
g
=
grad
(
x
);
double
unorm
=
0
;
for
(
long
i
=
0
;
i
<
g
.
size
();
++
i
)
{
if
(
lower
(
i
)
<
x
(
i
)
&&
x
(
i
)
<
upper
(
i
))
unorm
+=
g
(
i
)
*
g
(
i
);
else
if
(
x
(
i
)
==
lower
(
i
)
&&
g
(
i
)
<
0
)
unorm
+=
g
(
i
)
*
g
(
i
);
else
if
(
x
(
i
)
==
upper
(
i
)
&&
g
(
i
)
>
0
)
unorm
+=
g
(
i
)
*
g
(
i
);
}
return
unorm
;
}
template
<
typename
search_strategy_type
>
double
test_bound_solver_rosen
(
dlib
::
rand
&
rnd
,
search_strategy_type
search_strategy
)
{
using
namespace
dlib
::
test_functions
;
print_spinner
();
matrix
<
double
,
2
,
1
>
starting_point
,
lower
,
upper
,
x
;
// pick random bounds
lower
=
rnd
.
get_random_gaussian
()
+
1
,
rnd
.
get_random_gaussian
()
+
1
;
upper
=
rnd
.
get_random_gaussian
()
+
1
,
rnd
.
get_random_gaussian
()
+
1
;
while
(
upper
(
0
)
<
lower
(
0
))
upper
(
0
)
=
rnd
.
get_random_gaussian
()
+
1
;
while
(
upper
(
1
)
<
lower
(
1
))
upper
(
1
)
=
rnd
.
get_random_gaussian
()
+
1
;
starting_point
=
rnd
.
get_random_double
()
*
(
upper
(
0
)
-
lower
(
0
))
+
lower
(
0
),
rnd
.
get_random_double
()
*
(
upper
(
1
)
-
lower
(
1
))
+
lower
(
1
);
dlog
<<
LINFO
<<
"lower: "
<<
trans
(
lower
);
dlog
<<
LINFO
<<
"upper: "
<<
trans
(
upper
);
dlog
<<
LINFO
<<
"starting: "
<<
trans
(
starting_point
);
x
=
starting_point
;
find_min_box_constrained
(
search_strategy
,
objective_delta_stop_strategy
(
1e-16
,
500
),
rosen
,
der_rosen
,
x
,
lower
,
upper
);
dlog
<<
LINFO
<<
"rosen solution:
\n
"
<<
x
;
dlog
<<
LINFO
<<
"rosen gradient: "
<<
trans
(
der_rosen
(
x
));
const
double
gradient_residual
=
unconstrained_gradient_magnitude
(
der_rosen
,
x
,
lower
,
upper
);
dlog
<<
LINFO
<<
"gradient_residual: "
<<
gradient_residual
;
return
gradient_residual
;
}
template
<
typename
search_strategy_type
>
double
test_bound_solver_brown
(
dlib
::
rand
&
rnd
,
search_strategy_type
search_strategy
)
{
using
namespace
dlib
::
test_functions
;
print_spinner
();
matrix
<
double
,
4
,
1
>
starting_point
(
4
),
lower
(
4
),
upper
(
4
),
x
;
const
matrix
<
double
,
0
,
1
>
solution
=
brown_solution
();
// pick random bounds
lower
=
rnd
.
get_random_gaussian
(),
rnd
.
get_random_gaussian
(),
rnd
.
get_random_gaussian
(),
rnd
.
get_random_gaussian
();
lower
=
lower
*
10
+
solution
;
upper
=
rnd
.
get_random_gaussian
(),
rnd
.
get_random_gaussian
(),
rnd
.
get_random_gaussian
(),
rnd
.
get_random_gaussian
();
upper
=
upper
*
10
+
solution
;
for
(
int
i
=
0
;
i
<
lower
.
size
();
++
i
)
{
if
(
upper
(
i
)
<
lower
(
i
))
swap
(
upper
(
i
),
lower
(
i
));
}
starting_point
=
rnd
.
get_random_double
()
*
(
upper
(
0
)
-
lower
(
0
))
+
lower
(
0
),
rnd
.
get_random_double
()
*
(
upper
(
1
)
-
lower
(
1
))
+
lower
(
1
),
rnd
.
get_random_double
()
*
(
upper
(
2
)
-
lower
(
2
))
+
lower
(
2
),
rnd
.
get_random_double
()
*
(
upper
(
3
)
-
lower
(
3
))
+
lower
(
3
);
dlog
<<
LINFO
<<
"lower: "
<<
trans
(
lower
);
dlog
<<
LINFO
<<
"upper: "
<<
trans
(
upper
);
dlog
<<
LINFO
<<
"starting: "
<<
trans
(
starting_point
);
x
=
starting_point
;
find_min_box_constrained
(
search_strategy
,
objective_delta_stop_strategy
(
1e-16
,
500
),
brown
,
brown_derivative
,
x
,
lower
,
upper
);
dlog
<<
LINFO
<<
"brown solution:
\n
"
<<
x
;
return
unconstrained_gradient_magnitude
(
brown_derivative
,
x
,
lower
,
upper
);
}
template
<
typename
search_strategy_type
>
void
test_box_constrained_optimizers
(
search_strategy_type
search_strategy
)
{
dlog
<<
LINFO
<<
"test find_min_box_constrained() on rosen"
;
dlib
::
rand
rnd
;
running_stats
<
double
>
rs
;
for
(
int
i
=
0
;
i
<
1000
;
++
i
)
rs
.
add
(
test_bound_solver_rosen
(
rnd
,
search_strategy
));
dlog
<<
LINFO
<<
"mean rosen gradient: "
<<
rs
.
mean
();
dlog
<<
LINFO
<<
"max rosen gradient: "
<<
rs
.
max
();
DLIB_TEST
(
rs
.
mean
()
<
1e-12
);
DLIB_TEST
(
rs
.
max
()
<
1e-9
);
dlog
<<
LINFO
<<
"test find_min_box_constrained() on brown"
;
rs
.
clear
();
for
(
int
i
=
0
;
i
<
1000
;
++
i
)
rs
.
add
(
test_bound_solver_brown
(
rnd
,
search_strategy
));
dlog
<<
LINFO
<<
"mean brown gradient: "
<<
rs
.
mean
();
dlog
<<
LINFO
<<
"max brown gradient: "
<<
rs
.
max
();
DLIB_TEST
(
rs
.
mean
()
<
1e-6
);
DLIB_TEST
(
rs
.
max
()
<
1e-4
);
}
void
test_poly_min_extract_2nd
()
{
...
...
@@ -945,6 +1076,10 @@ namespace
void
perform_test
(
)
{
dlog
<<
LINFO
<<
"test_box_constrained_optimizers(bfgs_search_strategy())"
;
test_box_constrained_optimizers
(
bfgs_search_strategy
());
dlog
<<
LINFO
<<
"test_box_constrained_optimizers(lbfgs_search_strategy(5))"
;
test_box_constrained_optimizers
(
lbfgs_search_strategy
(
5
));
test_poly_min_extract_2nd
();
optimization_test
();
}
...
...
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