提交 b6684995 编写于 作者: S stevenj

autoconfiscated, and got to compile

darcs-hash:20070823151241-c8de0-892dec20933e93b9811997c9da167f4e2e40e16c.gz
上级 a4b2598d
NLopt was written/packaged by:
Steven G. Johnson <stevenj@alum.mit.edu>
See the subdirectories for the authors of the original nonlinear optimization
libraries utilized by NLopt.
NLopt combines several free/open-source nonlinear optimization libraries
by various authors. See the COPYING files in the subdirectories for the
original copyright and licensing information of these packages.
Other portions of NLopt, including any modifications to the abovementioned
packages, are licensed under the standard "MIT License:"
Copyright (c) 2007 Massachusetts Institute of Technology
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
/* Copyright (c) 2007 Massachusetts Institute of Technology
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
Generated automatically by 'make darcs-dist'
OPTIONS_AUTOMAKE=gnu
lib_LTLIBRARIES = libnlopt.la
ACLOCAL_AMFLAGS=-I ./m4
SUBDIRS=lbfgs subplex direct stogo api
EXTRA_DIST=COPYRIGHT autogen.sh nlopt.pc.in m4
libnlopt_la_SOURCES =
libnlopt_la_LIBADD = lbfgs/liblbfgs.la subplex/libsubplex.la direct/libdirect.la stogo/libstogo.la api/libapi.la
libnlopt_la_LDFLAGS = -no-undefined -version-info @SHARED_VERSION_INFO@
pkgconfigdir = $(libdir)/pkgconfig
pkgconfig_DATA = nlopt.pc
# Somewhat hackish. The "right" way to do this is by a dist-hook target,
# but then darcs check will fail because it doesn't run in the darcs
# repository.
darcs-dist: distdir
darcs changes --summary > $(distdir)/ChangeLog
tardir=$(distdir) && $(am__tar) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).tar.gz
$(am__remove_distdir)
No news yet.
NLopt is a library for nonlinear local and global optimization, for
functions with and without gradient information. It is designed as
as simple, unified interface and packaging of several free/open-source
nonlinear optimization libraries.
It is compiled and installed with the standard GNU autoconf/automake
commands:
./configure
make
make install
(See './configure --help' or the INSTALL file for other options.)
Once it is installed, #include <nlopt.h> in your C/C++ programs and
link it with -lnlopt -lm. You may need to use the C++ compiler to link
in order to include the C++ libraries (which are used internally by NLopt,
even though it has a C API).
Interfaces for other languages may be added in the future.
AM_CPPFLAGS = -I$(top_srcdir)/direct -I$(top_srcdir)/stogo -I$(top_srcdir)/lbfgs -I$(top_srcdir)/subplex
include_HEADERS = nlopt.h
noinst_LTLIBRARIES = libapi.la
libapi_la_SOURCES = nlopt.c nlopt.h
......@@ -2,6 +2,20 @@
#include <math.h>
#include "nlopt.h"
#include "config.h"
static int my_isinf(double x) {
return x == HUGE_VAL
#ifdef HAVE_ISINF
|| isinf(x)
#endif
;
}
#ifndef HAVE_ISNAN
static int my_isnan(double x) { return x != x; }
# define isnan my_isnan
#endif
typedef struct {
nlopt_func f;
......@@ -10,23 +24,26 @@ typedef struct {
#include "subplex.h"
double f_subplex(int n, const double *x, void *data_)
static double f_subplex(int n, const double *x, void *data_)
{
nlopt_data *data = (nlopt_data *) data_;
return data->f(n, x, NULL, f_data);
return data->f(n, x, NULL, data->f_data);
}
#include "direct.h"
double f_direct(int n, const double *x, int *undefined_flag, void *data_)
static double f_direct(int n, const double *x, int *undefined, void *data_)
{
nlopt_data *data = (nlopt_data *) data_;
double f = data->f(n, x, NULL, f_data);
*undefined_flag = isnan(f);
double f = data->f(n, x, NULL, data->f_data);
*undefined = isnan(f) || my_isinf(f);
return f;
}
#incude "stogo.h"
#include "stogo.h"
#include "l-bfgs-b.h"
#define MIN(a,b) ((a) < (b) ? (a) : (b))
nlopt_result nlopt_minimize(
nlopt_method method,
......@@ -34,7 +51,7 @@ nlopt_result nlopt_minimize(
const double *lb, const double *ub, /* bounds */
double *x, /* in: initial guess, out: minimizer */
double *fmin, /* out: minimum */
double fmin_max, ftol_rel, double ftol_abs,
double fmin_max, double ftol_rel, double ftol_abs,
double xtol_rel, const double *xtol_abs,
int maxeval, double maxtime)
{
......@@ -49,24 +66,24 @@ nlopt_result nlopt_minimize(
xtol_rel, xtol_rel,
DIRECT_UNKNOWN_FGLOBAL, -1.0,
NULL, DIRECT_GABLONSKY)) {
DIRECT_INVALID_BOUNDS:
DIRECT_MAXFEVAL_TOOBIG:
DIRECT_INVALID_ARGS:
return NLOPT_INVALID_ARGS;
DIRECT_INIT_FAILED:
DIRECT_SAMPLEPOINTS_FAILED:
DIRECT_SAMPLE_FAILED:
return NLOPT_FAILURE;
DIRECT_MAXFEVAL_EXCEEDED:
DIRECT_MAXITER_EXCEEDED:
return NLOPT_MAXEVAL_REACHED;
DIRECT_GLOBAL_FOUND:
return NLOPT_SUCCESS;
DIRECT_VOLTOL:
DIRECT_SIGMATOL:
return NLOPT_XTOL_REACHED;
DIRECT_OUT_OF_MEMORY:
return NLOPT_OUT_OF_MEMORY;
case DIRECT_INVALID_BOUNDS:
case DIRECT_MAXFEVAL_TOOBIG:
case DIRECT_INVALID_ARGS:
return NLOPT_INVALID_ARGS;
case DIRECT_INIT_FAILED:
case DIRECT_SAMPLEPOINTS_FAILED:
case DIRECT_SAMPLE_FAILED:
return NLOPT_FAILURE;
case DIRECT_MAXFEVAL_EXCEEDED:
case DIRECT_MAXITER_EXCEEDED:
return NLOPT_MAXEVAL_REACHED;
case DIRECT_GLOBAL_FOUND:
return NLOPT_SUCCESS;
case DIRECT_VOLTOL:
case DIRECT_SIGMATOL:
return NLOPT_XTOL_REACHED;
case DIRECT_OUT_OF_MEMORY:
return NLOPT_OUT_OF_MEMORY;
}
break;
......@@ -83,14 +100,14 @@ nlopt_result nlopt_minimize(
for (i = 0; i < n; ++i)
scale[i] = fabs(ub[i] - lb[i]);
iret = subplex(f_subplex, fmin, x, n, &d, xtol_rel, maxeval,
fmin_max, !isinf(fmin_max), scale);
fmin_max, !my_isinf(fmin_max), scale);
free(scale);
switch (iret) {
-2: return NLOPT_INVALID_ARGS;
-1: return NLOPT_MAXEVAL_REACHED;
0: return NLOPT_XTOL_REACHED;
1: return NLOPT_SUCCESS;
2: return NLOPT_FMIN_MAX_REACHED;
case -2: return NLOPT_INVALID_ARGS;
case -1: return NLOPT_MAXEVAL_REACHED;
case 0: return NLOPT_XTOL_REACHED;
case 1: return NLOPT_SUCCESS;
case 2: return NLOPT_FMIN_MAX_REACHED;
}
break;
}
......@@ -99,8 +116,8 @@ nlopt_result nlopt_minimize(
int iret, i, *nbd = (int *) malloc(sizeof(int) * n);
if (!nbd) return NLOPT_OUT_OF_MEMORY;
for (i = 0; i < n; ++i) {
int linf = isinf(lb[i]) && lb[i] < 0;
int uinf = isinf(ub[i]) && ub[i] > 0;
int linf = my_isinf(lb[i]) && lb[i] < 0;
int uinf = my_isinf(ub[i]) && ub[i] > 0;
nbd[i] = linf && uinf ? 0 : (uinf ? 1 : (linf ? 3 : 2));
}
iret = lbfgsb_minimize(n, f, f_data, x, nbd, lb, ub,
......@@ -110,16 +127,16 @@ nlopt_result nlopt_minimize(
free(nbd);
if (iret <= 0) {
switch (iret) {
-1: return NLOPT_INVALID_ARGS;
-2: default: return NLOPT_FAILURE;
case -1: return NLOPT_INVALID_ARGS;
case -2: default: return NLOPT_FAILURE;
}
}
else {
*fmin = f(n, x, NULL, f_data);
switch (iret) {
5: return NLOPT_MAXEVAL_REACHED;
2: return NLOPT_XTOL_REACHED;
1: return NLOPT_FTOL_REACHED;
case 5: return NLOPT_MAXEVAL_REACHED;
case 2: return NLOPT_XTOL_REACHED;
case 1: return NLOPT_FTOL_REACHED;
default: return NLOPT_SUCCESS;
}
}
......
......@@ -13,11 +13,11 @@ typedef double (*nlopt_func)(int n, const double *x,
typedef enum {
/* non-gradient methods */
NLOPT_GLOBAL_DIRECT,
NLOPT_LOCAL_SUBPLEX
NLOPT_LOCAL_SUBPLEX,
/* gradient-based methods */
NLOPT_GLOBAL_STOGO,
NLOPT_LOCAL_LBFGS,
NLOPT_LOCAL_LBFGS
} nlopt_method;
typedef enum {
......@@ -39,7 +39,7 @@ extern nlopt_result nlopt_minimize(
const double *lb, const double *ub, /* bounds */
double *x, /* in: initial guess, out: minimizer */
double *fmin, /* out: minimum */
double fmin_max, ftol_rel, double ftol_abs,
double fmin_max, double ftol_rel, double ftol_abs,
double xtol_rel, const double *xtol_abs,
int maxeval, double maxtime);
......
dnl Process this file with autoconf to produce a configure script.
AC_INIT(nlopt, 0.1, stevenj@alum.mit.edu)
AC_CONFIG_SRCDIR(api/nlopt.h)
SHARED_VERSION_INFO="0:0:0" # CURRENT:REVISION:AGE
AM_INIT_AUTOMAKE(1.7)
AM_CONFIG_HEADER(config.h)
AM_MAINTAINER_MODE
AC_SUBST(SHARED_VERSION_INFO)
AC_DISABLE_SHARED dnl to hell with shared libraries
dnl Checks for programs.
AC_PROG_CC
AC_PROG_CXX
AC_PROG_CC_STDC
AC_PROG_INSTALL
AC_PROG_LN_S
AC_PROG_MAKE_SET
AC_LIBTOOL_WIN32_DLL
AC_PROG_LIBTOOL
dnl Checks for typedefs, structures, and compiler characteristics.
AC_HEADER_STDC
AC_HEADER_TIME
AC_C_CONST
AC_C_INLINE
dnl Checks for libraries and functions
AC_CHECK_LIB(m, sin)
AC_CHECK_FUNCS([BSDgettimeofday gettimeofday])
AC_MSG_CHECKING([for isnan])
AC_TRY_LINK([#include <math.h>
], if (!isnan(3.14159)) isnan(2.7183);, ok=yes, ok=no)
if test "$ok" = "yes"; then
AC_DEFINE(HAVE_ISNAN,1,[Define if the isnan() function/macro is available.])
fi
AC_MSG_RESULT(${ok})
AC_MSG_CHECKING([for isinf])
AC_TRY_LINK([#include <math.h>
], if (!isinf(3.14159)) isinf(2.7183);, ok=yes, ok=no)
if test "$ok" = "yes"; then
AC_DEFINE(HAVE_ISINF,1,[Define if the isinf() function/macro is available.])
fi
AC_MSG_RESULT(${ok})
dnl -----------------------------------------------------------------------
dnl Debugging
AC_ARG_ENABLE(debug, [AC_HELP_STRING([--enable-debug],[compile with extra runtime checks for debugging])], ok=$enableval, ok=no)
if test "$ok" = "yes"; then
AC_DEFINE(DEBUG,1,[Define to enable extra debugging code.])
fi
dnl override CFLAGS selection when debugging
if test "${enable_debug}" = "yes"; then
CFLAGS="-g"
CXXFLAGS="-g"
FFLAGS="-g"
fi
dnl add gcc warnings, in debug/maintainer mode only
if test "$enable_debug" = yes || test "$USE_MAINTAINER_MODE" = yes; then
if test $ac_cv_prog_gcc = yes; then
if test "$ac_test_CFLAGS" != "set"; then
CFLAGS="$CFLAGS -Wall -W -Wcast-qual -Wpointer-arith -Wcast-align -pedantic -Wshadow -Wbad-function-cast -Wwrite-strings -Wstrict-prototypes -Wredundant-decls -Wnested-externs -Wundef -Wconversion -Wmissing-prototypes -Wmissing-declarations"
fi
if test "$ac_test_CXXFLAGS" != "set"; then
CXXFLAGS="$CXXFLAGS -Wall -W -Wcast-qual -Wpointer-arith -Wcast-align -pedantic -Wshadow -Wwrite-strings -Wredundant-decls -Wundef -Wconversion"
fi
fi
fi
dnl -----------------------------------------------------------------------
AC_CONFIG_FILES([
Makefile
nlopt.pc
api/Makefile
direct/Makefile
stogo/Makefile
lbfgs/Makefile
subplex/Makefile
])
AC_OUTPUT
......@@ -112,7 +112,7 @@ integer direct_dirgetlevel_(integer *pos, integer *length, integer *maxfunc, int
doublereal helplower;
integer i___, j___;
doublereal helpgreater;
integer novaluedeep;
integer novaluedeep = 0;
doublereal help2;
integer novalue;
......@@ -1363,102 +1363,6 @@ L50:
*free = 1;
} /* dirinitlist_ */
/* +-----------------------------------------------------------------------+ */
/* | SUBROUTINE DIRSort3 | */
/* +-----------------------------------------------------------------------+ */
/* Subroutine */ static void dirsort3_(integer *pos1, integer *pos2, integer *pos3,
doublereal *f, integer *maxfunc)
{
/* System generated locals */
integer f_dim1, f_offset;
/* Local variables */
integer help;
/* Parameter adjustments */
f_dim1 = *maxfunc;
f_offset = 1 + f_dim1;
f -= f_offset;
/* Function Body */
if (f[*pos1 + f_dim1] < f[*pos2 + f_dim1]) {
if (f[*pos1 + f_dim1] < f[*pos3 + f_dim1]) {
if (f[*pos3 + f_dim1] < f[*pos2 + f_dim1]) {
help = *pos2;
*pos2 = *pos3;
*pos3 = help;
}
} else {
help = *pos1;
*pos1 = *pos3;
*pos3 = *pos2;
*pos2 = help;
}
} else {
if (f[*pos2 + f_dim1] < f[*pos3 + f_dim1]) {
if (f[*pos3 + f_dim1] < f[*pos1 + f_dim1]) {
help = *pos1;
*pos1 = *pos2;
*pos2 = *pos3;
*pos3 = help;
} else {
help = *pos1;
*pos1 = *pos2;
*pos2 = help;
}
} else {
help = *pos1;
*pos1 = *pos3;
*pos3 = help;
}
}
} /* dirsort3_ */
/* +-----------------------------------------------------------------------+ */
/* | SUBROUTINE DIRInsert3 | */
/* +-----------------------------------------------------------------------+ */
/* Subroutine */ void direct_dirinsert3_(integer *pos1, integer *pos2, integer *pos3,
integer *deep, integer *anchor, integer *point, integer *free,
doublereal *f, doublereal *fmin, integer *minpos, integer *maxfunc,
integer *maxdeep)
{
/* System generated locals */
integer f_dim1, f_offset;
/* Local variables */
integer pos;
/* Parameter adjustments */
f_dim1 = *maxfunc;
f_offset = 1 + f_dim1;
f -= f_offset;
--point;
++anchor;
/* Function Body */
dirsort3_(pos1, pos2, pos3, &f[f_offset], maxfunc);
if (anchor[*deep] == 0) {
anchor[*deep] = *pos1;
point[*pos1] = *pos2;
point[*pos2] = *pos3;
point[*pos3] = 0;
} else {
pos = anchor[*deep];
if (f[*pos1 + f_dim1] < f[pos + f_dim1]) {
anchor[*deep] = *pos1;
point[*pos1] = pos;
} else {
dirinsert_(&pos, pos1, &point[1], &f[f_offset], maxfunc);
}
dirinsert_(&pos, pos2, &point[1], &f[f_offset], maxfunc);
dirinsert_(&pos, pos3, &point[1], &f[f_offset], maxfunc);
}
if (f[*pos1 + f_dim1] < *fmin && f[*pos1 + (f_dim1 << 1)] == 0.) {
*fmin = f[*pos1 + f_dim1];
*minpos = *pos1;
}
} /* dirinsert3_ */
/* +-----------------------------------------------------------------------+ */
/* | | */
/* | SUBROUTINE DIRPREPRC | */
......@@ -1689,27 +1593,3 @@ L50:
}
} /* dirsummary_ */
/* Subroutine */ void direct_dirmaxf_to_high1__(integer *maxf, integer *maxfunc,
FILE *logfile)
{
if (logfile) {
fprintf(logfile,
"The maximum number of function evaluations (%d)\n"
"is higher than the constant maxfunc (%d). Increase maxfunc\n"
"in the SUBROUTINE DIRECT or decrease the maximum number\n"
"of function evaluations.\n", *maxf, *maxfunc);
}
} /* dirmaxf_to_high1__ */
/* Subroutine */ void direct_dirmaxt_to_high1__(integer *maxt, integer *maxdeep,
FILE *logfile)
{
if (logfile) {
fprintf(logfile,
"The maximum number of iterations (%d) is higher than the constant\n"
"maxdeep (%d). Increase maxdeep or decrease the number of iterations.\n",
*maxt, *maxdeep);
}
} /* dirmaxt_to_high1__ */
noinst_LTLIBRARIES = libdirect.la
libdirect_la_SOURCES = DIRect.c direct_wrap.c DIRserial.c DIRsubrout.c \
direct-internal.h direct.h
EXTRA_DIST = AUTHORS COPYING DIRparallel.c tstc.c userguide.ps.gz
......@@ -21,16 +21,6 @@ typedef direct_objective_func fp;
#define MIN(a,b) ((a) < (b) ? (a) : (b))
#define MAX(a,b) ((a) > (b) ? (a) : (b))
/* DIRect.c */
extern void direct_dirsamplef_(
doublereal *c__, integer *arrayi, doublereal
*delta, integer *sample, integer *new__, integer *length,
FILE *logfile, doublereal *f, integer *free, integer *maxi,
integer *point, fp fcn, doublereal *x, doublereal *l, doublereal *
fmin, integer *minpos, doublereal *u, integer *n, integer *maxfunc,
integer *maxdeep, integer *oops, doublereal *fmax, integer *
ifeasiblef, integer *iinfesiblef, void *fcndata);
/* DIRsubrout.c */
extern void direct_dirheader_(
......@@ -115,7 +105,6 @@ extern void direct_dirsamplef_(
ifeasiblef, integer *iinfesiblef, void *fcn_data);
/* DIRect.c */
extern void direct_direct_(
fp fcn, doublereal *x, integer *n, doublereal *eps, doublereal epsabs,
integer *maxf, integer *maxt, doublereal *fmin, doublereal *l,
......
......@@ -2,6 +2,7 @@
#define DIRECT_H
#include <math.h>
#include <stdio.h>
#ifdef __cplusplus
extern "C"
......
noinst_LTLIBRARIES = liblbfgs.la
liblbfgs_la_SOURCES = ap.cpp ap.h l-bfgs-b.cpp l-bfgs-b.h
EXTRA_DIST =
prefix=@prefix@
exec_prefix=@exec_prefix@
libdir=@libdir@
includedir=@includedir@
Name: NLopt
Description: nonlinear optimization libary
Version: @VERSION@
Libs: -L${libdir} -lnlopt -lm
Cflags: -I${includedir}
noinst_LTLIBRARIES = libstogo.la
libstogo_la_SOURCES = global.cc linalg.cc local.cc stogo.cc tools.cc \
global.h linalg.h local.h stogo_config.h stogo.h tools.h
EXTRA_DIST = testros.cc tst.cc tstc.c prog.cc testfun.h rosen.h README
......@@ -44,8 +44,8 @@ public:
return Objective(xy);
case GRADIENT_ONLY:
Gradient(xy, grad);
return 0.0;
}
return 0.0;
}
Global(RTBox, Pobj, Pgrad, GlobalParams);
......
......@@ -22,6 +22,7 @@ public:
case OBJECTIVE_ONLY:
return my_func(xy.GetLength(), xy.raw_data_const(), NULL, my_data);
}
return 0.0;
}
};
......
noinst_LTLIBRARIES = libsubplex.la
libsubplex_la_SOURCES = subplex.c subplex.h
EXTRA_DIST = README
......@@ -252,7 +252,7 @@ L40:
-lf2c -lm (in that order)
*/
static int dcopy_(integer *n, doublereal *dx, integer *incx,
static int dcopy_(integer *n, const doublereal *dx, integer *incx,
doublereal *dy, integer *incy)
{
/* System generated locals */
......@@ -422,9 +422,6 @@ static doublereal dist_(integer *n, doublereal *x, doublereal *y)
integer i__1;
doublereal ret_val, d__1;
/* Builtin functions */
double sqrt(doublereal);
/* Local variables */
integer i__;
doublereal scale, absxmy, sum;
......@@ -1071,9 +1068,6 @@ static int fstats_(doublereal *fx, integer *ifxwt, logical *reset)
/* System generated locals */
doublereal d__1, d__2, d__3;
/* Builtin functions */
double sqrt(doublereal);
/* Local variables */
static doublereal fscale;
static integer nsv;
......@@ -1797,7 +1791,7 @@ static int setstp_(integer *nsubs, integer *n, doublereal *deltax,
*/
static int subplx_(D_fp f, void *fdata, integer *n, doublereal *tol, integer *
maxnfe, integer *mode, doublereal *scale, doublereal *x, doublereal *
maxnfe, integer *mode, const doublereal *scale, doublereal *x, doublereal *
fx, integer *nfe, doublereal *work, integer *iwork, integer *iflag)
{
/* Initialized data */
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册